
- Add model.py for wok - Add an empty json API to wok - Move some basic Javascript APIs from kimchi - Do not load tabs.xml anymore - Disable wok authentication by default - Rename KimchiRoot to WokRoot - Update default_page to wok-ui.html - Adapt 'sample' plugin - Move hide-content css to wok Signed-off-by: Lucio Correia <luciojhc@linux.vnet.ibm.com> Signed-off-by: Gustavo Y. Ribeiro <gyr@linux.vnet.ibm.com> --- plugins/kimchi/ui/css/theme-default/storage.css | 4 - plugins/sample/__init__.py | 4 +- src/wok/API.json | 6 ++ src/wok/config.py.in | 1 + src/wok/model/model.py | 49 ++++++++++++ src/wok/root.py | 10 +- src/wok/server.py | 8 +- src/wok/utils.py | 2 +- ui/css/theme-default/topbar.css | 4 + ui/js/src/wok.api.js | 91 +++++++++++++++++++++++ ui/js/src/wok.main.js | 3 +- 11 files changed, 164 insertions(+), 18 deletions(-) create mode 100644 src/wok/API.json create mode 100644 src/wok/model/model.py create mode 100644 ui/js/src/wok.api.js diff --git a/plugins/kimchi/ui/css/theme-default/storage.css b/plugins/kimchi/ui/css/theme-default/storage.css index 519a28b..d30a5a7 100644 --- a/plugins/kimchi/ui/css/theme-default/storage.css +++ b/plugins/kimchi/ui/css/theme-default/storage.css @@ -319,10 +319,6 @@ border: 1px solid rgb(204, 204, 204); } -.hide-content { - display: none!important; -} - .volumeslist { padding: 7px; max-height: 272px; diff --git a/plugins/sample/__init__.py b/plugins/sample/__init__.py index 786832f..3a309a5 100644 --- a/plugins/sample/__init__.py +++ b/plugins/sample/__init__.py @@ -26,7 +26,7 @@ from cherrypy import expose from wok.config import PluginPaths from wok.control.base import Collection, Resource -from wok.root import Root +from wok.root import WokRoot from plugins.sample.i18n import messages from plugins.sample.model import Model @@ -34,7 +34,7 @@ from plugins.sample.model import Model model = Model() -class Drawings(Root): +class Drawings(WokRoot): def __init__(self): Resource.__init__(self, model) self.description = Description(model) diff --git a/src/wok/API.json b/src/wok/API.json new file mode 100644 index 0000000..8965db9 --- /dev/null +++ b/src/wok/API.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-03/schema#", + "title": "Wok API", + "description": "Json schema for Wok API", + "type": "object" +} diff --git a/src/wok/config.py.in b/src/wok/config.py.in index 4c97840..390ba3b 100644 --- a/src/wok/config.py.in +++ b/src/wok/config.py.in @@ -180,6 +180,7 @@ class UIConfig(dict): ui_configs['/' + sub_dir] = { 'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(paths.ui_dir, sub_dir), + 'tools.wokauth.on': False, 'tools.nocache.on': False} if sub_dir != 'images': ui_configs['/' + sub_dir].update({ diff --git a/src/wok/model/model.py b/src/wok/model/model.py new file mode 100644 index 0000000..09c4c1e --- /dev/null +++ b/src/wok/model/model.py @@ -0,0 +1,49 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2014-2015 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import inspect +import os + +from wok.basemodel import BaseModel +from wok.objectstore import ObjectStore +from wok.utils import import_module, listPathModules + + +class Model(BaseModel): + def __init__(self, objstore_loc=None): + + self.objstore = ObjectStore(objstore_loc) + kargs = {'objstore': self.objstore} + + this = os.path.basename(__file__) + this_mod = os.path.splitext(this)[0] + + models = [] + for mod_name in listPathModules(os.path.dirname(__file__)): + if mod_name.startswith("_") or mod_name == this_mod: + continue + + module = import_module('wok.model.' + mod_name) + members = inspect.getmembers(module, inspect.isclass) + for cls_name, instance in members: + if inspect.getmodule(instance) == module: + if cls_name.endswith('Model'): + models.append(instance(**kargs)) + + return super(Model, self).__init__(models) diff --git a/src/wok/root.py b/src/wok/root.py index a3b8be1..35620c7 100644 --- a/src/wok/root.py +++ b/src/wok/root.py @@ -114,16 +114,16 @@ class Root(Resource): raise cherrypy.HTTPError(404) -class KimchiRoot(Root): - def __init__(self, model, dev_env): - super(KimchiRoot, self).__init__(model, dev_env) - self.default_page = 'kimchi-ui.html' +class WokRoot(Root): + def __init__(self, model, dev_env=False): + super(WokRoot, self).__init__(model, dev_env) + self.default_page = 'wok-ui.html' for ident, node in sub_nodes.items(): setattr(self, ident, node(model)) with open(os.path.join(paths.src_dir, 'API.json')) as f: self.api_schema = json.load(f) self.paths = paths - self.domain = 'kimchi' + self.domain = 'wok' self.messages = messages @cherrypy.expose diff --git a/src/wok/server.py b/src/wok/server.py index 0f99663..ab941e7 100644 --- a/src/wok/server.py +++ b/src/wok/server.py @@ -28,10 +28,10 @@ from wok import config from wok.model import model from wok import mockmodel from wok import vnc -from wok.config import KimchiConfig, PluginConfig +from wok.config import WokConfig, PluginConfig from wok.control import sub_nodes from wok.proxy import start_proxy, terminate_proxy -from wok.root import KimchiRoot +from wok.root import WokRoot from wok.utils import get_enabled_plugins, import_class @@ -73,7 +73,7 @@ class Server(object): if not os.path.isdir(directory): os.makedirs(directory) - self.configObj = KimchiConfig() + self.configObj = WokConfig() # We'll use the session timeout (= 10 minutes) and the # nginx timeout (= 10 minutes). This monitor isn't involved # in anything other than monitor the timeout of the connection, @@ -141,7 +141,7 @@ class Server(object): ident = "/%s" % ident cfg[ident] = {'tools.wokauth.on': True} - self.app = cherrypy.tree.mount(KimchiRoot(model_instance, dev_env), + self.app = cherrypy.tree.mount(WokRoot(model_instance, dev_env), config=self.configObj) self._load_plugins() diff --git a/src/wok/utils.py b/src/wok/utils.py index f5058d5..fc76620 100644 --- a/src/wok/utils.py +++ b/src/wok/utils.py @@ -113,7 +113,7 @@ def get_enabled_plugins(): def get_all_tabs(): - files = [os.path.join(paths.prefix, 'config/ui/tabs.xml')] + files = [] for plugin, _ in get_enabled_plugins(): files.append(os.path.join(PluginPaths(plugin).ui_dir, diff --git a/ui/css/theme-default/topbar.css b/ui/css/theme-default/topbar.css index 9dd5ec1..4fce02c 100644 --- a/ui/css/theme-default/topbar.css +++ b/ui/css/theme-default/topbar.css @@ -208,3 +208,7 @@ a#btn-logout:hover { display: block; padding: 10px; } + +.hide-content { + display: none!important; +} diff --git a/ui/js/src/wok.api.js b/ui/js/src/wok.api.js new file mode 100644 index 0000000..93a07ad --- /dev/null +++ b/ui/js/src/wok.api.js @@ -0,0 +1,91 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2015 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var wok = { + + widget: {}, + + /** + * A wrapper of jQuery.ajax function to allow custom bindings. + * + * @param settings an extended object to jQuery Ajax settings object + * with some extra properties (see below) + * + * resend: if the XHR has failed due to 401, the XHR can be resent + * after user being authenticated successfully by setting resend + * to true: settings = {resend: true}. It's useful for switching + * pages (Guests, Templates, etc.). + * e.g., the user wants to list guests by clicking Guests tab, + * but he is told not authorized and a login window will pop up. + * After login, the Ajax request for /vms will be resent without + * user clicking the tab again. + * Default to false. + */ + requestJSON : function(settings) { + settings['originalError'] = settings['error']; + settings['error'] = null; + settings['wok'] = true; + return $.ajax(settings); + }, + + /** + * Get the i18 strings. + */ + getI18n: function(suc, err, url, sync) { + wok.requestJSON({ + url : url ? url : 'i18n.json', + type : 'GET', + resend: true, + dataType : 'json', + async : !sync, + success : suc, + error: err + }); + }, + + login : function(settings, suc, err) { + $.ajax({ + url : "login", + type : "POST", + contentType : "application/json", + data : JSON.stringify(settings), + dataType : "json" + }).done(suc).fail(err); + }, + + logout : function(suc, err) { + wok.requestJSON({ + url : 'logout', + type : 'POST', + contentType : "application/json", + dataType : "json" + }).done(suc).fail(err); + }, + + listPlugins : function(suc, err, sync) { + wok.requestJSON({ + url : 'plugins', + type : 'GET', + contentType : 'application/json', + dataType : 'json', + resend: true, + async : !sync, + success : suc, + error : err + }); + }, +}; diff --git a/ui/js/src/wok.main.js b/ui/js/src/wok.main.js index 089b523..5b1f1bc 100644 --- a/ui/js/src/wok.main.js +++ b/ui/js/src/wok.main.js @@ -90,12 +90,11 @@ wok.main = function() { return tabs; }; - var tabConfigUrl = 'config/ui/tabs.xml'; var pluginConfigUrl = 'plugins/{plugin}/ui/config/tab-ext.xml'; var pluginI18nUrl = 'plugins/{plugin}/i18n.json'; var DEFAULT_HASH; var buildTabs = function(callback) { - var tabs = retrieveTabs(tabConfigUrl); + var tabs = []; wok.listPlugins(function(plugins) { $(plugins).each(function(i, p) { var url = wok.substitute(pluginConfigUrl, { -- 1.7.1