[Kimchi-devel] [RFC PATCH V2 15/31] Setup kimchi plugin

Lucio Correia luciojhc at linux.vnet.ibm.com
Mon Jun 22 22:59:29 UTC 2015


- 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 at linux.vnet.ibm.com>
Signed-off-by: Gustavo Y. Ribeiro <gyr at 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@/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




More information about the Kimchi-devel mailing list