[Kimchi-devel] [PATCH 18/38] Setup kimchi plugin
Lucio Correia
luciojhc at linux.vnet.ibm.com
Thu May 21 21:33:31 UTC 2015
- Create kimchi.conf and config.py in plugin
- Move kimchi specific config/API to plugin
- Rename Kimchi{Config,Root} to Wok{Config,Root}
- Create root.py in plugin with new KimchiRoot
- Adjust tabs-ext.xml and do not load tabs.xml anymore
- Drop login/logout functions from plugin API
---
plugins/kimchi/__init__.py | 21 +++++++
plugins/kimchi/config.py.in | 74 ++++++++++++++++++++++++
plugins/kimchi/kimchi.conf | 67 +++++++++++++++++++++
plugins/kimchi/root.py | 57 ++++++++++++++++++
plugins/kimchi/ui/config/tab-ext.xml | 14 ++--
plugins/kimchi/ui/js/src/kimchi.api.js | 19 ------
src/wok/config.py.in | 99 --------------------------------
src/wok/root.py | 8 +-
src/wok/server.py | 20 ++----
src/wok/utils.py | 2 +-
ui/js/src/wok.main.js | 3 +-
11 files changed, 239 insertions(+), 145 deletions(-)
create mode 100644 plugins/kimchi/__init__.py
create mode 100644 plugins/kimchi/config.py.in
create mode 100644 plugins/kimchi/kimchi.conf
create mode 100644 plugins/kimchi/root.py
diff --git a/plugins/kimchi/__init__.py b/plugins/kimchi/__init__.py
new file mode 100644
index 0000000..9330044
--- /dev/null
+++ b/plugins/kimchi/__init__.py
@@ -0,0 +1,21 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013-2014
+#
+# 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
+
+from root import KimchiRoot
+__all__ = [KimchiRoot]
diff --git a/plugins/kimchi/config.py.in b/plugins/kimchi/config.py.in
new file mode 100644
index 0000000..fdf360a
--- /dev/null
+++ b/plugins/kimchi/config.py.in
@@ -0,0 +1,74 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013-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 libvirt
+import os
+import platform
+import threading
+
+from wok.config import PluginPaths
+from wok.xmlutils.utils import xpath_get_text
+
+kimchiLock = threading.Lock()
+
+# Storage pool constant for read-only pool types
+READONLY_POOL_TYPE = ['iscsi', 'scsi', 'mpath']
+
+
+def get_distros_store():
+ return os.path.join(PluginPaths('kimchi').conf_dir, 'distros.d')
+
+
+def get_debugreports_path():
+ return os.path.join(PluginPaths('kimchi').state_dir, 'debugreports')
+
+
+def get_screenshot_path():
+ return os.path.join(PluginPaths('kimchi').state_dir, 'screenshots')
+
+
+def find_qemu_binary(find_emulator=False):
+ try:
+ connect = libvirt.open(None)
+ except Exception, e:
+ raise Exception("Unable to get qemu binary location: %s" % e)
+ try:
+ xml = connect.getCapabilities()
+
+ # On Little Endian system, the qemu binary is
+ # qemu-system-ppc64, not qemu-system-ppc64le as expected
+ arch = platform.machine()
+ if arch == "ppc64le":
+ arch = "ppc64"
+
+ if find_emulator:
+ expr = "/capabilities/guest/arch[@name='%s']\
+ /emulator" % arch
+ else:
+ expr = "/capabilities/guest/arch[@name='%s']\
+ /domain[@type='kvm']/emulator" % arch
+ res = xpath_get_text(xml, expr)
+ location = res[0]
+ except Exception, e:
+ raise Exception("Unable to get qemu binary location: %s" % e)
+ finally:
+ connect.close()
+ return location
+
diff --git a/plugins/kimchi/kimchi.conf b/plugins/kimchi/kimchi.conf
new file mode 100644
index 0000000..07ade54
--- /dev/null
+++ b/plugins/kimchi/kimchi.conf
@@ -0,0 +1,67 @@
+[wok]
+enable = True
+plugin_class = "KimchiRoot"
+uri = "/plugins/kimchi"
+
+[/]
+tools.trailing_slash.on = False
+request.methods_with_bodies = ('POST', 'PUT')
+tools.nocache.on = True
+tools.proxy.on = True
+tools.sessions.on = True
+tools.sessions.name = 'wok'
+tools.sessions.secure = True
+tools.sessions.httponly = True
+tools.sessions.locking = 'explicit'
+tools.sessions.storage_type = 'ram'
+tools.sessions.timeout = 10
+tools.wokauth.on = True
+
+[/novnc]
+tools.staticdir.on = True
+tools.staticdir.dir = wok.config.PluginPaths('kimchi').novnc_dir
+tools.nocache.on = True
+tools.wokauth.on = True
+
+[/spice_auto.html]
+tools.staticfile.on = True
+tools.staticfile.filename = wok.config.PluginPaths('kimchi').spice_file
+tools.nocache.on = True
+tools.wokauth.on = True
+
+[/spice-html5]
+tools.staticdir.on = True
+tools.staticdir.dir = wok.config.PluginPaths('kimchi').spice_dir
+tools.nocache.on = True
+
+[/spice-html5/spice.css]
+tools.staticfile.on = True
+tools.staticfile.filename = wok.config.PluginPaths('kimchi').spice_css_file
+tools.nocache.on = True
+
+[/data/screenshots]
+tools.staticdir.on = True
+tools.staticdir.dir = wok.config.PluginPaths('kimchi').state_dir + '/screenshots'
+tools.nocache.on = False
+
+[/data/debugreports]
+tools.staticdir.on = True
+tools.staticdir.dir = wok.config.PluginPaths('kimchi').state_dir + '/debugreports'
+tools.nocache.on = False
+tools.wokauth.on = True
+tools.staticdir.content_types = {'xz': 'application/x-xz'}
+
+[/favicon.ico]
+tools.staticfile.on = True
+tools.staticfile.filename = wok.config.PluginPaths('kimchi').ui_dir + '/images/logo.ico'
+
+[/robots.txt]
+tools.staticfile.on = True
+tools.staticfile.filename = wok.config.PluginPaths('kimchi').ui_dir + '/robots.txt'
+
+[/help]
+tools.staticdir.on = True
+tools.staticdir.dir = wok.config.PluginPaths('kimchi').ui_dir + '/pages/help'
+tools.nocache.on = True
+tools.staticdir.index = 'en_US/index.html'
+
diff --git a/plugins/kimchi/root.py b/plugins/kimchi/root.py
new file mode 100644
index 0000000..c05a6cb
--- /dev/null
+++ b/plugins/kimchi/root.py
@@ -0,0 +1,57 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013-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 json
+import os
+
+
+import config
+from control import sub_nodes
+from wok.i18n import messages
+from wok.config import PluginPaths
+from model import model as kimchiModel
+from wok.root import WokRoot
+
+
+class KimchiRoot(WokRoot):
+ def __init__(self, model=None, dev_env=False):
+ if not model:
+ self.model = kimchiModel.Model()
+ else:
+ self.model = model
+ super(KimchiRoot, self).__init__(self.model, dev_env)
+
+ for ident, node in sub_nodes.items():
+ setattr(self, ident, node(self.model))
+
+ self.api_schema = json.load(open(os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), 'API.json')))
+ self.paths = PluginPaths('kimchi')
+ self.domain = 'kimchi'
+ self.messages = messages
+
+ make_dirs = [
+ os.path.abspath(config.get_distros_store()),
+ os.path.abspath(config.get_debugreports_path()),
+ os.path.abspath(config.get_screenshot_path())
+ ]
+ for directory in make_dirs:
+ if not os.path.isdir(directory):
+ os.makedirs(directory)
+
diff --git a/plugins/kimchi/ui/config/tab-ext.xml b/plugins/kimchi/ui/config/tab-ext.xml
index f79684c..ee88c88 100644
--- a/plugins/kimchi/ui/config/tab-ext.xml
+++ b/plugins/kimchi/ui/config/tab-ext.xml
@@ -1,38 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
-<tabs>
+<tabs-ext>
<tab>
<access role="admin" mode="admin"/>
<access role="user" mode="none"/>
<title>Host</title>
- <path>tabs/host.html</path>
+ <path>plugins/kimchi/host.html</path>
</tab>
<tab>
<access role="admin" mode="admin"/>
<access role="user" mode="byInstance"/>
<title>Guests</title>
- <path>tabs/guests.html</path>
+ <path>plugins/kimchi/guests.html</path>
</tab>
<tab>
<access role="admin" mode="admin"/>
<access role="user" mode="none"/>
<title>Templates</title>
- <path>tabs/templates.html</path>
+ <path>plugins/kimchi/templates.html</path>
</tab>
<tab>
<access role="admin" mode="admin"/>
<access role="user" mode="read-only"/>
<title>Storage</title>
- <path>tabs/storage.html</path>
+ <path>plugins/kimchi/storage.html</path>
</tab>
<tab>
<access role="admin" mode="admin"/>
<access role="user" mode="read-only"/>
<title>Network</title>
- <path>tabs/network.html</path>
+ <path>plugins/kimchi/network.html</path>
</tab>
-</tabs>
+</tabs-ext>
diff --git a/plugins/kimchi/ui/js/src/kimchi.api.js b/plugins/kimchi/ui/js/src/kimchi.api.js
index a74d660..ba1b762 100644
--- a/plugins/kimchi/ui/js/src/kimchi.api.js
+++ b/plugins/kimchi/ui/js/src/kimchi.api.js
@@ -547,25 +547,6 @@ var kimchi = {
});
},
- 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) {
- kimchi.requestJSON({
- url : 'logout',
- type : 'POST',
- contentType : "application/json",
- dataType : "json"
- }).done(suc).fail(err);
- },
-
deleteStoragePool : function(poolName, suc, err) {
$.ajax({
url : 'plugins/kimchi/storagepools/' + encodeURIComponent(poolName),
diff --git a/src/wok/config.py.in b/src/wok/config.py.in
index 390ba3b..2951539 100644
--- a/src/wok/config.py.in
+++ b/src/wok/config.py.in
@@ -18,78 +18,27 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
-import libvirt
import os
-import platform
-import threading
from ConfigParser import SafeConfigParser
-from kimchi.xmlutils.utils import xpath_get_text
-
__version__ = "@wokversion@"
__release__ = "@wokrelease@"
__with_spice__ = "@withspice@"
DEFAULT_LOG_LEVEL = "debug"
-kimchiLock = threading.Lock()
-
-# Storage pool constant for read-only pool types
-READONLY_POOL_TYPE = ['iscsi', 'scsi', 'mpath']
-
def get_object_store():
return os.path.join(paths.state_dir, 'objectstore')
-def get_distros_store():
- return os.path.join(paths.conf_dir, 'distros.d')
-
-
-def get_screenshot_path():
- return os.path.join(paths.state_dir, 'screenshots')
-
-
-def get_debugreports_path():
- return os.path.join(paths.state_dir, 'debugreports')
-
-
def get_version():
return "-".join([__version__, __release__])
-def find_qemu_binary(find_emulator=False):
- try:
- connect = libvirt.open(None)
- except Exception, e:
- raise Exception("Unable to get qemu binary location: %s" % e)
- try:
- xml = connect.getCapabilities()
-
- # On Little Endian system, the qemu binary is
- # qemu-system-ppc64, not qemu-system-ppc64le as expected
- arch = platform.machine()
- if arch == "ppc64le":
- arch = "ppc64"
-
- if find_emulator:
- expr = "/capabilities/guest/arch[@name='%s']\
- /emulator" % arch
- else:
- expr = "/capabilities/guest/arch[@name='%s']\
- /domain[@type='kvm']/emulator" % arch
- res = xpath_get_text(xml, expr)
- location = res[0]
- except Exception, e:
- raise Exception("Unable to get qemu binary location: %s" % e)
- finally:
- connect.close()
- return location
-
-
class Paths(object):
def __init__(self):
@@ -214,57 +163,9 @@ class WokConfig(dict):
'tools.nocache.on': True,
'tools.wokauth.on': True
},
- '/spice_auto.html': {
- 'tools.staticfile.on': True,
- 'tools.staticfile.filename': paths.spice_file,
- 'tools.nocache.on': True,
- 'tools.kimchiauth.on': True
- },
- '/spice-html5': {
- 'tools.staticdir.on': True,
- 'tools.staticdir.dir': paths.spice_dir,
- 'tools.nocache.on': True
- },
- '/spice-html5/spice.css': {
- 'tools.staticfile.on': True,
- 'tools.staticfile.filename': paths.spice_css_file,
- 'tools.nocache.on': True,
- },
'/wok-ui.html': {
'tools.wokauth.on': True
},
- '/data/screenshots': {
- 'tools.staticdir.on': True,
- 'tools.staticdir.dir': get_screenshot_path(),
- 'tools.nocache.on': False
- },
- '/data/debugreports': {
- 'tools.staticdir.on': True,
- 'tools.staticdir.dir': get_debugreports_path(),
- 'tools.nocache.on': False,
- 'tools.kimchiauth.on': True,
- 'tools.staticdir.content_types': {'xz': 'application/x-xz'}
- },
- '/config/ui/tabs.xml': {
- 'tools.staticfile.on': True,
- 'tools.staticfile.filename': '%s/config/ui/tabs.xml' %
- paths.prefix,
- 'tools.nocache.on': True
- },
- '/favicon.ico': {
- 'tools.staticfile.on': True,
- 'tools.staticfile.filename': '%s/images/logo.ico' % paths.ui_dir
- },
- '/robots.txt': {
- 'tools.staticfile.on': True,
- 'tools.staticfile.filename': '%s/robots.txt' % paths.ui_dir
- },
- '/help': {
- 'tools.staticdir.on': True,
- 'tools.staticdir.dir': '%s/ui/pages/help' % paths.prefix,
- 'tools.staticdir.index': 'en_US/index.html',
- 'tools.nocache.on': True
- }
}
def __init__(self):
diff --git a/src/wok/root.py b/src/wok/root.py
index a3b8be1..2b4ad44 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):
+class WokRoot(Root):
def __init__(self, model, dev_env):
- super(KimchiRoot, self).__init__(model, dev_env)
- self.default_page = 'kimchi-ui.html'
+ 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..711c24f 100644
--- a/src/wok/server.py
+++ b/src/wok/server.py
@@ -25,13 +25,12 @@ import os
from wok import auth
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.model import model
+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
@@ -64,16 +63,13 @@ class Server(object):
make_dirs = [
os.path.dirname(os.path.abspath(options.access_log)),
os.path.dirname(os.path.abspath(options.error_log)),
- os.path.dirname(os.path.abspath(config.get_object_store())),
- os.path.abspath(config.get_screenshot_path()),
- os.path.abspath(config.get_debugreports_path()),
- os.path.abspath(config.get_distros_store())
+ os.path.dirname(os.path.abspath(config.get_object_store()))
]
for directory in make_dirs:
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,
@@ -126,12 +122,10 @@ class Server(object):
if hasattr(options, 'model'):
model_instance = options.model
- elif options.test:
- model_instance = mockmodel.MockModel()
else:
model_instance = model.Model()
- if isinstance(model_instance, model.Model):
+ if isinstance(model_instance, model.Model) and not options.test:
vnc_ws_proxy = vnc.new_ws_proxy()
cherrypy.engine.subscribe('exit', vnc_ws_proxy.terminate)
@@ -141,7 +135,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 267cd3e..42e753d 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/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
More information about the Kimchi-devel
mailing list