- Create root.py, kimchi.conf and config.py.in in plugin
- Adjust tabs-ext.xml
- Move kimchi specific config/API from wok to plugin
- Move mockmodel stuff to plugin
- Create mechanism to load plugin-specific config through
get_custom_conf() method in plugin root and use it for
novnc/spice config moved to new classes KimchiPaths and
KimchiConfig
- Pass all server options in plugins initalization
- Adapt sample plugin to receive server options
- Drop server-specific functions from kimchi plugin
- Move kimchi-specific URI functions to plugin
- Move capabilities to kimchi plugin
Signed-off-by: Lucio Correia <luciojhc(a)linux.vnet.ibm.com>
Signed-off-by: Gustavo Y. Ribeiro <gyr(a)linux.vnet.ibm.com>
---
plugins/kimchi/__init__.py | 21 +++
plugins/kimchi/config.py.in | 139 ++++++++++++++++++++
plugins/kimchi/kimchi.conf | 45 +++++++
plugins/kimchi/root.py | 70 ++++++++++
plugins/kimchi/ui/config/tab-ext.xml | 14 +-
plugins/kimchi/ui/js/src/kimchi.api.js | 55 --------
plugins/kimchi/ui/js/src/kimchi.guest_edit_main.js | 6 +-
plugins/kimchi/ui/js/src/kimchi.host.js | 12 +-
plugins/kimchi/ui/js/src/kimchi.main.js | 26 ++++
.../ui/js/src/kimchi.repository_edit_main.js | 4 +-
.../kimchi/ui/js/src/kimchi.template_add_main.js | 4 +-
.../kimchi/ui/js/src/kimchi.template_edit_main.js | 4 +-
plugins/kimchi/utils.py | 40 ++++++
plugins/sample/__init__.py | 2 +-
src/wok/config.py.in | 122 -----------------
src/wok/server.py | 25 ++--
src/wok/utils.py | 16 ---
ui/js/src/wok.main.js | 10 --
18 files changed, 374 insertions(+), 241 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
create mode 100644 plugins/kimchi/ui/js/src/kimchi.main.js
create mode 100644 plugins/kimchi/utils.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..80b72bd
--- /dev/null
+++ b/plugins/kimchi/config.py.in
@@ -0,0 +1,139 @@
+#
+# 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()
+
+__with_spice__ = "@withspice@"
+
+# 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
+
+
+class KimchiPaths(PluginPaths):
+
+ def __init__(self):
+ super(KimchiPaths, self).__init__('kimchi')
+ self.spice_file = os.path.join(self.ui_dir,
+ 'spice-html5/pages/spice_auto.html')
+
+ if __with_spice__ == 'yes':
+ self.spice_dir = self.add_prefix('ui/spice-html5')
+ elif os.path.exists('@datadir@/spice-html5'):
+ self.spice_dir = '@datadir@/spice-html5'
+ else:
+ self.spice_dir = '/usr/share/spice-html5'
+
+ if os.path.exists('@datadir@/novnc'):
+ self.novnc_dir = '@datadir@/novnc'
+ else:
+ self.novnc_dir = '/usr/share/novnc'
+
+ if self.installed:
+ self.spice_css_file = os.path.join(self.spice_dir, 'spice.css')
+ else:
+ self.spice_css_file = os.path.join(self.spice_dir, 'css/spice.css')
+
+
+kimchiPaths = KimchiPaths()
+
+
+class KimchiConfig(dict):
+ def __init__(self):
+ super(KimchiConfig, self).__init__(self)
+
+ custom_config = {
+ '/novnc': {
+ 'tools.staticdir.on': True,
+ 'tools.staticdir.dir': kimchiPaths.novnc_dir,
+ 'tools.nocache.on': True,
+ 'tools.wokauth.on': True,
+ },
+
+ '/spice_auto.html': {
+ 'tools.staticfile.on': True,
+ 'tools.staticfile.filename': kimchiPaths.spice_file,
+ 'tools.nocache.on': True,
+ 'tools.wokauth.on': True,
+ },
+
+ '/spice-html5': {
+ 'tools.staticdir.on': True,
+ 'tools.staticdir.dir': kimchiPaths.spice_dir,
+ 'tools.nocache.on': True,
+ },
+
+ '/spice-html5/spice.css': {
+ 'tools.staticfile.on': True,
+ 'tools.staticfile.filename': kimchiPaths.spice_css_file,
+ 'tools.nocache.on': True,
+ },
+ }
+
+ self.update(custom_config)
+
diff --git a/plugins/kimchi/kimchi.conf b/plugins/kimchi/kimchi.conf
new file mode 100644
index 0000000..1e0ee6b
--- /dev/null
+++ b/plugins/kimchi/kimchi.conf
@@ -0,0 +1,45 @@
+[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
+
+[/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..9889926
--- /dev/null
+++ b/plugins/kimchi/root.py
@@ -0,0 +1,70 @@
+#
+# 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 cherrypy
+
+
+import config
+import mockmodel
+from control import sub_nodes
+from wok.i18n import messages
+from model import model as kimchiModel
+from wok.root import WokRoot
+from wok import vnc
+
+
+class KimchiRoot(WokRoot):
+ def __init__(self, wok_options):
+ if hasattr(wok_options, "model"):
+ self.model = wok_options.model
+ elif wok_options.test:
+ self.model = mockmodel.MockModel()
+ else:
+ self.model = kimchiModel.Model()
+
+ dev_env = wok_options.environment != 'production'
+ super(KimchiRoot, self).__init__(self.model, dev_env)
+
+ for ident, node in sub_nodes.items():
+ setattr(self, ident, node(self.model))
+
+ if isinstance(self.model, kimchiModel.Model):
+ vnc_ws_proxy = vnc.new_ws_proxy()
+ cherrypy.engine.subscribe('exit', vnc_ws_proxy.terminate)
+
+ self.api_schema = json.load(open(os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), 'API.json')))
+ self.paths = config.kimchiPaths
+ 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)
+
+ def get_custom_conf(self):
+ return config.KimchiConfig()
+
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 d4d0c83..0ec3747 100644
--- a/plugins/kimchi/ui/js/src/kimchi.api.js
+++ b/plugins/kimchi/ui/js/src/kimchi.api.js
@@ -22,29 +22,6 @@ var kimchi = {
trackingTasks: [],
/**
- * 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['kimchi'] = true;
- return $.ajax(settings);
- },
-
- /**
*
* Get host capabilities
* suc: callback if succeed err: callback if failed
@@ -569,25 +546,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),
@@ -611,19 +569,6 @@ var kimchi = {
});
},
- listPlugins : function(suc, err, sync) {
- kimchi.requestJSON({
- url : 'plugins',
- type : 'GET',
- contentType : 'application/json',
- dataType : 'json',
- resend: true,
- async : !sync,
- success : suc,
- error : err
- });
- },
-
listNetworks : function(suc, err) {
wok.requestJSON({
url : 'plugins/kimchi/networks',
diff --git a/plugins/kimchi/ui/js/src/kimchi.guest_edit_main.js
b/plugins/kimchi/ui/js/src/kimchi.guest_edit_main.js
index 25e3703..7105c88 100644
--- a/plugins/kimchi/ui/js/src/kimchi.guest_edit_main.js
+++ b/plugins/kimchi/ui/js/src/kimchi.guest_edit_main.js
@@ -314,7 +314,7 @@ kimchi.guest_edit_main = function() {
};
//set up for PAM
var userNodes = {}, groupNodes = {};
- authType = wok.capabilities['auth']
+ authType = kimchi.capabilities['auth']
if (authType == 'pam') {
$("#form-guest-edit-permission .ldap").hide();
kimchi.retrieveVM(kimchi.selectedGuest, function(vm){
@@ -432,7 +432,7 @@ kimchi.guest_edit_main = function() {
var setupPCIDevice = function(){
kimchi.getHostPCIDevices(function(hostPCIs){
kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs){
- var pciEnabled = wok.capabilities.kernel_vfio;
+ var pciEnabled = kimchi.capabilities.kernel_vfio;
for(var i=0; i<hostPCIs.length; i++){
var itemNode =
$.parseHTML(wok.substitute($('#pci-tmpl').html(),{
name: hostPCIs[i].name,
@@ -708,7 +708,7 @@ kimchi.guest_edit_main = function() {
var permissionSubmit = function(event) {
var content = { users: [], groups: [] };
- authType = wok.capabilities['auth']
+ authType = kimchi.capabilities['auth']
if (authType == 'pam') {
$("#permission-sel-users").children().each(function(){
content.users.push($("label", this).text());
diff --git a/plugins/kimchi/ui/js/src/kimchi.host.js
b/plugins/kimchi/ui/js/src/kimchi.host.js
index 4218d97..ab02333 100644
--- a/plugins/kimchi/ui/js/src/kimchi.host.js
+++ b/plugins/kimchi/ui/js/src/kimchi.host.js
@@ -507,14 +507,14 @@ kimchi.host_main = function() {
});
var setupUI = function() {
- if (wok.capabilities == undefined) {
+ if (kimchi.capabilities == undefined) {
setTimeout(setupUI, 2000);
return;
}
- if((wok.capabilities['repo_mngt_tool']) &&
(wok.capabilities['repo_mngt_tool']!="None")) {
- initRepositoriesGrid(wok.capabilities['repo_mngt_tool']);
- $('#repositories-section').switchClass('hidden',
wok.capabilities['repo_mngt_tool']);
+ if((kimchi.capabilities['repo_mngt_tool']) &&
(kimchi.capabilities['repo_mngt_tool']!="None")) {
+ initRepositoriesGrid(kimchi.capabilities['repo_mngt_tool']);
+ $('#repositories-section').switchClass('hidden',
kimchi.capabilities['repo_mngt_tool']);
wok.topic('kimchi/repositoryAdded')
.subscribe(listRepositories);
wok.topic('kimchi/repositoryUpdated')
@@ -523,7 +523,7 @@ kimchi.host_main = function() {
.subscribe(listRepositories);
}
- if(wok.capabilities['update_tool']) {
+ if(kimchi.capabilities['update_tool']) {
$('#software-update-section').removeClass('hidden');
initSoftwareUpdatesGrid();
wok.topic('kimchi/softwareUpdated')
@@ -533,7 +533,7 @@ kimchi.host_main = function() {
});
}
- if(wok.capabilities['system_report_tool']) {
+ if(kimchi.capabilities['system_report_tool']) {
listDebugReports();
wok.topic('kimchi/debugReportAdded')
.subscribe(listDebugReports);
diff --git a/plugins/kimchi/ui/js/src/kimchi.main.js
b/plugins/kimchi/ui/js/src/kimchi.main.js
new file mode 100644
index 0000000..2fdeb85
--- /dev/null
+++ b/plugins/kimchi/ui/js/src/kimchi.main.js
@@ -0,0 +1,26 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2014
+ *
+ * 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.
+ */
+kimchi.capabilities = undefined;
+kimchi.getCapabilities(function(result) {
+ kimchi.capabilities = result;
+
+ if(kimchi.capabilities.federation=="on")
+ $('#peers').removeClass('hide-content');
+}, function() {
+ kimchi.capabilities = {};
+});
diff --git a/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js
b/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js
index 85e24d4..5bfc51e 100644
--- a/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js
+++ b/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js
@@ -21,10 +21,10 @@ kimchi.repository_edit_main = function() {
var saveButton = $('#repository-edit-button-save');
- if(wok.capabilities['repo_mngt_tool']=="yum") {
+ if(kimchi.capabilities['repo_mngt_tool']=="yum") {
editForm.find('input.deb').prop('disabled', true);
}
- else if(wok.capabilities['repo_mngt_tool']=="deb") {
+ else if(kimchi.capabilities['repo_mngt_tool']=="deb") {
editForm.find('input.yum').prop('disabled', true);
}
diff --git a/plugins/kimchi/ui/js/src/kimchi.template_add_main.js
b/plugins/kimchi/ui/js/src/kimchi.template_add_main.js
index 5528eb2..01a47c2 100644
--- a/plugins/kimchi/ui/js/src/kimchi.template_add_main.js
+++ b/plugins/kimchi/ui/js/src/kimchi.template_add_main.js
@@ -224,12 +224,12 @@ kimchi.template_add_main = function() {
$('#iso-remote').css('opacity', 0.3).css('cursor',
'not-allowed');
var enabledRemoteIso = function() {
- if (wok.capabilities == undefined) {
+ if (kimchi.capabilities == undefined) {
setTimeout(enabledRemoteIso, 2000);
return;
}
- if (wok.capabilities.qemu_stream != true) {
+ if (kimchi.capabilities.qemu_stream != true) {
return;
}
diff --git a/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js
b/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js
index 6df1328..b00d596 100644
--- a/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js
+++ b/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js
@@ -49,11 +49,11 @@ kimchi.template_edit_main = function() {
$('#template-edit-graphics').append('<option>Spice</option>');
kimchi.select('template-edit-graphics-list', vncOpt);
var enableSpice = function() {
- if (wok.capabilities == undefined) {
+ if (kimchi.capabilities == undefined) {
setTimeout(enableSpice, 2000);
return;
}
- if (wok.capabilities.qemu_spice == true) {
+ if (kimchi.capabilities.qemu_spice == true) {
spiceOpt = [{label: 'Spice', value: 'spice'}]
kimchi.select('template-edit-graphics-list', spiceOpt);
}
diff --git a/plugins/kimchi/utils.py b/plugins/kimchi/utils.py
new file mode 100644
index 0000000..dc00481
--- /dev/null
+++ b/plugins/kimchi/utils.py
@@ -0,0 +1,40 @@
+#
+# 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 re
+
+from wok.exception import InvalidParameter
+
+
+def _uri_to_name(collection, uri):
+ expr = '/plugins/kimchi/%s/(.*?)$' % collection
+ m = re.match(expr, uri)
+ if not m:
+ raise InvalidParameter("KCHUTILS0001E", {'uri': uri})
+ return m.group(1)
+
+
+def template_name_from_uri(uri):
+ return _uri_to_name('templates', uri)
+
+
+def pool_name_from_uri(uri):
+ return _uri_to_name('storagepools', uri)
+
diff --git a/plugins/sample/__init__.py b/plugins/sample/__init__.py
index 3a309a5..a2cfbf2 100644
--- a/plugins/sample/__init__.py
+++ b/plugins/sample/__init__.py
@@ -35,7 +35,7 @@ model = Model()
class Drawings(WokRoot):
- def __init__(self):
+ def __init__(self, wok_options):
Resource.__init__(self, model)
self.description = Description(model)
self.rectangles = Rectangles(model)
diff --git a/src/wok/config.py.in b/src/wok/config.py.in
index 390ba3b..c676f89 100644
--- a/src/wok/config.py.in
+++ b/src/wok/config.py.in
@@ -18,98 +18,32 @@
# 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):
self.prefix = self.get_prefix()
self.installed = (self.prefix == '@pkgdatadir@')
self.ui_dir = self.add_prefix('ui')
- self.spice_file = os.path.join(self.ui_dir,
- 'spice-html5/pages/spice_auto.html')
-
- if __with_spice__ == 'yes':
- self.spice_dir = self.add_prefix('ui/spice-html5')
- elif os.path.exists('@datadir@/spice-html5'):
- self.spice_dir = '@datadir@/spice-html5'
- else:
- self.spice_dir = '/usr/share/spice-html5'
-
- if os.path.exists('@datadir@/novnc'):
- self.novnc_dir = '@datadir@/novnc'
- else:
- self.novnc_dir = '/usr/share/novnc'
if self.installed:
self.nginx_conf_dir = '@sysconfdir(a)/nginx/conf.d'
@@ -119,7 +53,6 @@ class Paths(object):
self.src_dir = '@wokdir@'
self.plugins_dir = '@wokdir@/plugins'
self.mo_dir = '@prefix@/share/locale'
- self.spice_css_file = os.path.join(self.spice_dir, 'spice.css')
else:
self.nginx_conf_dir = self.add_prefix('src/nginx')
self.state_dir = self.add_prefix('data')
@@ -128,7 +61,6 @@ class Paths(object):
self.src_dir = self.add_prefix('src/wok')
self.plugins_dir = self.add_prefix('plugins')
self.mo_dir = self.add_prefix('mo')
- self.spice_css_file = os.path.join(self.spice_dir, 'css/spice.css')
def get_prefix(self):
if __file__.startswith("/"):
@@ -208,63 +140,9 @@ class WokConfig(dict):
'tools.sessions.timeout': SESSIONSTIMEOUT,
'tools.wokauth.on': False
},
- '/novnc': {
- 'tools.staticdir.on': True,
- 'tools.staticdir.dir': paths.novnc_dir,
- '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/server.py b/src/wok/server.py
index ab941e7..ba81308 100644
--- a/src/wok/server.py
+++ b/src/wok/server.py
@@ -26,8 +26,6 @@ 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 WokConfig, PluginConfig
from wok.control import sub_nodes
from wok.proxy import start_proxy, terminate_proxy
@@ -64,10 +62,7 @@ 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):
@@ -126,15 +121,9 @@ 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):
- vnc_ws_proxy = vnc.new_ws_proxy()
- cherrypy.engine.subscribe('exit', vnc_ws_proxy.terminate)
-
for ident, node in sub_nodes.items():
if node.url_auth:
cfg = self.configObj
@@ -143,14 +132,14 @@ class Server(object):
self.app = cherrypy.tree.mount(WokRoot(model_instance, dev_env),
config=self.configObj)
- self._load_plugins()
+ self._load_plugins(options)
# Terminate proxy when cherrypy server is terminated
cherrypy.engine.subscribe('exit', terminate_proxy)
cherrypy.lib.sessions.init()
- def _load_plugins(self):
+ def _load_plugins(self, options):
for plugin_name, plugin_config in get_enabled_plugins():
try:
plugin_class = ('plugins.%s.%s' %
@@ -164,11 +153,17 @@ class Server(object):
continue
try:
- plugin_app = import_class(plugin_class)()
+ plugin_app = import_class(plugin_class)(options)
except ImportError:
cherrypy.log.error_log.error("Failed to import plugin %s" %
plugin_class)
continue
+
+ # dynamically extend plugin config with custom data, if provided
+ get_custom_conf = getattr(plugin_app, "get_custom_conf", None)
+ if get_custom_conf is not None:
+ plugin_config.update(get_custom_conf())
+
cherrypy.tree.mount(plugin_app, script_name, plugin_config)
def start(self):
diff --git a/src/wok/utils.py b/src/wok/utils.py
index fc76620..af0d200 100644
--- a/src/wok/utils.py
+++ b/src/wok/utils.py
@@ -44,22 +44,6 @@ wok_log = cherrypy.log.error_log
task_id = 0
-def _uri_to_name(collection, uri):
- expr = '/%s/(.*?)$' % collection
- m = re.match(expr, uri)
- if not m:
- raise InvalidParameter("KCHUTILS0001E", {'uri': uri})
- return m.group(1)
-
-
-def template_name_from_uri(uri):
- return _uri_to_name('templates', uri)
-
-
-def pool_name_from_uri(uri):
- return _uri_to_name('storagepools', uri)
-
-
def get_next_task_id():
global task_id
task_id += 1
diff --git a/ui/js/src/wok.main.js b/ui/js/src/wok.main.js
index 5b1f1bc..b7797dd 100644
--- a/ui/js/src/wok.main.js
+++ b/ui/js/src/wok.main.js
@@ -17,16 +17,6 @@
*/
wok.tabMode = {};
-wok.capabilities = undefined;
-wok.getCapabilities(function(result) {
- wok.capabilities = result;
-
- if(wok.capabilities.federation=="on")
- $('#peers').removeClass('hide-content');
-}, function() {
- wok.capabilities = {};
-});
-
wok.main = function() {
wok.isLoggingOut = false;
wok.popable();
--
1.7.1