[Kimchi-devel] [PATCH] Take off libvirt to get vms info used before any shutdown and reboot actions

chandra at linux.vnet.ibm.com chandra at linux.vnet.ibm.com
Tue Nov 3 06:45:54 UTC 2015


From: chandrureddy <chandra at linux.vnet.ibm.com>

Earlier been used libvirt to fetch the vms information in the back end code
UI was using REST API 'plugins/kimchi/vms' to get the vms info.
Ginger Base not have this functionality and will not work on plain linux.
Ginger Base should handle well on both plain linux with out KVM and with KVM

New code provides REST API 'plugins/gingerbase/vms'
1. to get the vms information on KVM mahcine (virsh way)
2. return empty json in case of plain linux machine
---
 src/wok/plugins/gingerbase/control/vmsinfo.py      | 34 +++++++++++++
 src/wok/plugins/gingerbase/i18n.py                 |  1 +
 src/wok/plugins/gingerbase/model/host.py           | 23 +++------
 src/wok/plugins/gingerbase/model/vmsinfo.py        | 32 ++++++++++++
 .../plugins/gingerbase/ui/js/src/gingerbase.api.js | 12 +++++
 .../gingerbase/ui/js/src/gingerbase.host.js        | 23 ++++-----
 src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl |  2 +
 src/wok/plugins/gingerbase/utils.py                | 59 +++++++++++++++++++++-
 8 files changed, 157 insertions(+), 29 deletions(-)
 create mode 100644 src/wok/plugins/gingerbase/control/vmsinfo.py
 create mode 100644 src/wok/plugins/gingerbase/model/vmsinfo.py

diff --git a/src/wok/plugins/gingerbase/control/vmsinfo.py b/src/wok/plugins/gingerbase/control/vmsinfo.py
new file mode 100644
index 0000000..e9bddea
--- /dev/null
+++ b/src/wok/plugins/gingerbase/control/vmsinfo.py
@@ -0,0 +1,34 @@
+#
+# Project Ginger Base
+#
+# Copyright IBM, Corp. 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
+
+from wok.control.utils import UrlSubNode
+from wok.control.base import SimpleCollection
+
+
+ at UrlSubNode('vms', True)
+class VMs(SimpleCollection):
+    def __init__(self, model):
+        super(VMs, self).__init__(model)
+        self.role_key = 'host'
+        self.admin_methods = ['GET']
+        self.uri_fmt = '/vms/%s'
+
+    @property
+    def data(self):
+        return self.info
diff --git a/src/wok/plugins/gingerbase/i18n.py b/src/wok/plugins/gingerbase/i18n.py
index 8596f17..d477b20 100644
--- a/src/wok/plugins/gingerbase/i18n.py
+++ b/src/wok/plugins/gingerbase/i18n.py
@@ -40,6 +40,7 @@ messages = {
     "GGBHOST0001E": _("Unable to shutdown host machine as there are running virtual machines"),
     "GGBHOST0002E": _("Unable to reboot host machine as there are running virtual machines"),
     "GGBHOST0005E": _("When specifying CPU topology, each element must be an integer greater than zero."),
+    "GGBHOST0006E": _("Failed to execute virsh command"),
 
     "GGBPKGUPD0001E": _("No packages marked for update"),
     "GGBPKGUPD0002E": _("Package %(name)s is not marked to be updated."),
diff --git a/src/wok/plugins/gingerbase/model/host.py b/src/wok/plugins/gingerbase/model/host.py
index 670fec5..307f26a 100644
--- a/src/wok/plugins/gingerbase/model/host.py
+++ b/src/wok/plugins/gingerbase/model/host.py
@@ -37,6 +37,7 @@ from wok.model.tasks import TaskModel
 from wok.plugins.gingerbase.model.debugreports import DebugReportsModel
 from wok.plugins.gingerbase.repositories import Repositories
 from wok.plugins.gingerbase.swupdate import SoftwareUpdate
+from wok.plugins.gingerbase.utils import get_vms_by_state
 
 HOST_STATS_INTERVAL = 1
 
@@ -142,30 +143,22 @@ class HostModel(object):
 
     def shutdown(self, args=None):
         # Check for running vms before shutdown
-        # FIXME : Find alternative way to figure out if any vms running
-        # running_vms = self._get_vms_list_by_state('running')
-        # if len(running_vms) > 0:
-        #     raise OperationFailed("GGBHOST0001E")
+        running_vms = get_vms_by_state('running')
+        if len(running_vms) > 0:
+            raise OperationFailed("GGBHOST0001E")
 
         wok_log.info('Host is going to shutdown.')
         os.system('shutdown -h now')
 
     def reboot(self, args=None):
-        # Find running VMs
-        # FIXME : Find alternative way to figure out if any vms running
-        # running_vms = self._get_vms_list_by_state('running')
-        # if len(running_vms) > 0:
-        #     raise OperationFailed("GGBHOST0002E")
+        # Check for running vms before reboot
+        running_vms = get_vms_by_state('running')
+        if len(running_vms) > 0:
+            raise OperationFailed("GGBHOST0002E")
 
         wok_log.info('Host is going to reboot.')
         os.system('reboot')
 
-    # def _get_vms_list_by_state(self, state):
-    #     conn = self.conn.get()
-    #     return [dom.name().decode('utf-8')
-    #             for dom in conn.listAllDomains(0)
-    #             if (DOM_STATE_MAP[dom.info()[0]]) == state]
-
 
 class SoftwareUpdateProgressModel(object):
     def __init__(self, **kargs):
diff --git a/src/wok/plugins/gingerbase/model/vmsinfo.py b/src/wok/plugins/gingerbase/model/vmsinfo.py
new file mode 100644
index 0000000..a9895df
--- /dev/null
+++ b/src/wok/plugins/gingerbase/model/vmsinfo.py
@@ -0,0 +1,32 @@
+#
+# Project Ginger Base
+#
+# Copyright IBM, Corp. 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
+
+from wok.model.tasks import TaskModel
+from wok.plugins.gingerbase.utils import get_vms
+
+
+class VMsModel(object):
+    def __init__(self, **kargs):
+        self.objstore = kargs['objstore']
+        self.task = TaskModel(**kargs)
+        self.vms_info = get_vms()
+
+    def get_list(self, *name):
+        self.vms_info = get_vms()
+        return self.vms_info
diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js
index db6543f..9cd3b4a 100644
--- a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js
+++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js
@@ -358,5 +358,17 @@ var kimchi = {
                 wok.message.error(data.responseJSON.reason);
             }
         });
+    },
+
+    listVMs : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/vms',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend: true,
+            success : suc,
+            error : err
+        });
     }
 };
diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js
index 0d52b92..ea64dad 100644
--- a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js
+++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js
@@ -500,18 +500,17 @@ kimchi.host_main = function() {
             $(shutdownButtonID).prop('disabled', true);
             $(restartButtonID).prop('disabled', true);
             // Check if there is any VM is running.
-            // FIXME : Find alternative way to figure out if any vms running
-            // kimchi.listVMs(function(vms) {
-            //     for(var i = 0; i < vms.length; i++) {
-            //         if(vms[i]['state'] === 'running') {
-            //             wok.message.error.code('GGBHOST6001E');
-            //             $(shutdownButtonID).prop('disabled', false);
-            //             $(restartButtonID).prop('disabled', false);
-            //             return;
-            //         }
-            //     }
-            //
-            // });
+            kimchi.listVMs(function(vms) {
+                for(var i = 0; i < vms.length; i++) {
+                    if(vms[i]['state'] === 'running') {
+                        wok.message.error.code('GGBHOST6001E');
+                        $(shutdownButtonID).prop('disabled', false);
+                        $(restartButtonID).prop('disabled', false);
+                        return;
+                    }
+                }
+
+            });
         }, function() {
         });
     };
diff --git a/src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl b/src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl
index f6228ab..346e76f 100644
--- a/src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl
+++ b/src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl
@@ -113,6 +113,8 @@
     "GGBDR6012M": "$_("Pending...")",
     "GGBDR6013M": "$_("Report name is the same as the original one.")",
 
+    "GGBHOST6001E": "$_("Unable to shut down system as there are some virtual machines running!")",
+
     "GGBVM6001M": "$_("This will delete the virtual machine and its virtual disks. This operation cannot be undone. Would you like to continue?")",
     "GGBVM6002M": "$_("Power off Confirmation")",
     "GGBVM6003M": "$_("This action may produce undesirable results, "
diff --git a/src/wok/plugins/gingerbase/utils.py b/src/wok/plugins/gingerbase/utils.py
index 9f41967..b606438 100644
--- a/src/wok/plugins/gingerbase/utils.py
+++ b/src/wok/plugins/gingerbase/utils.py
@@ -22,12 +22,13 @@
 
 import contextlib
 import os
+import re
 import urllib2
 from httplib import HTTPConnection, HTTPException
 from urlparse import urlparse
 
-from wok.exception import InvalidParameter
-
+from wok.exception import InvalidParameter, OperationFailed
+from wok.utils import run_command, wok_log
 
 MAX_REDIRECTION_ALLOWED = 5
 
@@ -80,3 +81,57 @@ def validate_repo_url(url):
             raise InvalidParameter("WOKUTILS0001E", {'url': url})
     else:
         raise InvalidParameter("KCHREPOS0002E")
+
+
+def get_vms():
+    # Check for vms running on the machine
+    # virsh -r -c 'qemu:///system' list --all
+    #  Id    Name                           State
+    # ----------------------------------------------------
+    #  3     Fedora21                       running
+    #  -     a8Sr0LzRgWjEqy3iiKjQvA         shut off
+    #  -     kimchi-cdrom                   shut off
+    #  -     kimchi-ifaces                  shut off
+    vms = []
+    try:
+        __import__('libvirt')
+        vms_running = ["virsh", "-r", "-c", "qemu:///system", "list", "--all"]
+        (std_out, std_err, rc) = run_command(vms_running)
+
+        if rc == 0:
+            header_pattern = r'('+re.escape('Id') + r')\s+' \
+                             r'('+re.escape('Name') + r')\s+' \
+                             r'('+re.escape('State') + r')$'
+
+            vm_pattern = r'([-]|[0-9]+)\s+' \
+                         r'([0-9a-zA-Z-_]*)\s+' \
+                         r'([a-zA-Z-_]+[\s]?[a-zA-Z-_]+)'
+            command_out = std_out.strip().split("\n")
+            header = re.search(header_pattern, command_out[0], re.M | re.I)
+
+            value_pattern = re.compile(vm_pattern, re.M | re.I)
+            for line in command_out[2:]:
+                value = re.search(value_pattern, line)
+                vm_data = {}
+                if value:
+                    if (header.group() != value.group()) and \
+                            (len(header.groups()) == len(value.groups())):
+                        for cnt in range(1, len(header.groups())+1):
+                            vm_data[header.group(cnt).lower()] = \
+                                value.group(cnt)
+                vms.append(vm_data)
+        else:
+            raise OperationFailed('GGBHOST0006E')
+    except ImportError, err:
+        wok_log.info('Host is running linux with out KVM. %s' % err.message)
+        return []
+    return vms
+
+
+def get_vms_by_state(state='running'):
+    vms_running = []
+    vms = get_vms()
+    for vm in vms:
+        if vm['state'] == state:
+            vms_running.append(vm)
+    return vms_running
-- 
2.1.0




More information about the Kimchi-devel mailing list