[Kimchi-devel] [PATCH] [Kimchi] Add support to Libvirt Events.

pvital at linux.vnet.ibm.com pvital at linux.vnet.ibm.com
Thu Mar 24 18:59:22 UTC 2016


From: Paulo Vital <pvital at linux.vnet.ibm.com>

This patch adds support to handle in Kimchi any Libvirt Event, just by adding
a callback to process the event and register the event with the callback.

A method called register_common_events() is responsible to register the common
domain events to use a generic callback that logs into error log, the event
happened and it's details.

This patch is part of the solution for Kimchi Issue #817

Signed-off-by: Paulo Vital <pvital at linux.vnet.ibm.com>
---
 i18n.py                |  4 ++
 model/libvirtevents.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++
 model/model.py         |  6 ++-
 3 files changed, 108 insertions(+), 1 deletion(-)
 create mode 100644 model/libvirtevents.py

diff --git a/i18n.py b/i18n.py
index 6214687..3939aba 100644
--- a/i18n.py
+++ b/i18n.py
@@ -326,4 +326,8 @@ messages = {

     "KCHLVMS0001E": _("Invalid volume group name parameter: %(name)s."),

+    "KCHEVENT0001E": _("Failed to register the default event implementation."),
+    "KCHEVENT0002E": _("Failed to register timeout event."),
+    "KCHEVENT0003E": _("Failed to Run the default event implementation."),
+
 }
diff --git a/model/libvirtevents.py b/model/libvirtevents.py
new file mode 100644
index 0000000..44da18f
--- /dev/null
+++ b/model/libvirtevents.py
@@ -0,0 +1,99 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2016
+#
+# 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 cherrypy
+import libvirt
+import time
+
+from wok.exception import OperationFailed
+from wok.utils import wok_log
+
+
+class LibvirtEvents(object):
+    def __init__(self):
+        # Register default implementation of event handlers
+        if libvirt.virEventRegisterDefaultImpl() < 0:
+            raise OperationFailed('KCHEVENT0001E')
+
+        # Run a background thread with the event loop. Using cherrypy
+        # BackgroundTask class due to issues when using threading module with
+        # cherrypy.
+        self.event_loop_thread = cherrypy.process.plugins.BackgroundTask(
+            2,
+            self._event_loop_run
+        )
+        self.event_loop_thread.setName('KimchiLibvirtEventLoop')
+        self.event_loop_thread.setDaemon(True)
+        self.event_loop_thread.start()
+
+        # Set an event timeout to control the self._event_loop_run
+        if libvirt.virEventAddTimeout(0, self._kimchi_EventTimeout, None) < 0:
+            raise OperationFailed('KCHEVENT0002E')
+
+        # List to control which domains are using events
+        self.vms_tracked = []
+
+    # Event loop method to be executed in background as thread
+    def _event_loop_run(self):
+        while True:
+            if libvirt.virEventRunDefaultImpl() < 0:
+                raise OperationFailed('KCHEVENT0003E')
+
+    def is_event_loop_alive(self):
+        return self.event_loop_thread.isAlive()
+
+    # Event loop handler used to limit length of waiting for any other event.
+    def _kimchi_EventTimeout(self, timer, opaque):
+        time.sleep(1)
+
+    def event_generic_cb(self, conn, dom, event, detail, *args):
+        """
+        Generic callback to handle Domain (VMs) events.
+        """
+        evStrings = ("Defined", "Undefined", "Started", "Suspended", "Resumed",
+                     "Stopped", "Shutdown", "PMSuspended", "Crashed")
+        evDetails = (("Added", "Updated"),
+                     ("Removed", ),
+                     ("Booted", "Migrated", "Restored", "Snapshot", "Wakeup"),
+                     ("Paused", "Migrated", "IOError", "Watchdog", "Restored",
+                      "Snapshot", "API error"),
+                     ("Unpaused", "Migrated", "Snapshot"),
+                     ("Shutdown", "Destroyed", "Crashed", "Migrated", "Saved",
+                      "Failed", "Snapshot"),
+                     ("Finished", ),
+                     ("Memory", "Disk"),
+                     ("Panicked"))
+        msg = "Libvirt Event: Domain %s %s %s" % (dom.name(), evStrings[event],
+                                                  evDetails[event][detail])
+
+        wok_log.error(msg)
+
+    def register_common_events(self, conn):
+        """
+        Register the most common Libvirt events to be handled.
+        """
+        conn = conn.get()
+        for ev in (libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+                   libvirt.VIR_DOMAIN_EVENT_ID_REBOOT,
+                   libvirt.VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
+                   libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
+                   libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS,
+                   libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
+                   libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG):
+            conn.domainEventRegisterAny(None, ev, self.event_generic_cb, ev)
diff --git a/model/model.py b/model/model.py
index e44f804..dd50ec2 100644
--- a/model/model.py
+++ b/model/model.py
@@ -26,6 +26,7 @@ from wok.plugins.kimchi import config
 from wok.utils import import_module, listPathModules

 from wok.plugins.kimchi.model.libvirtconnection import LibvirtConnection
+from wok.plugins.kimchi.model.libvirtevents import LibvirtEvents


 class Model(BaseModel):
@@ -43,8 +44,11 @@ class Model(BaseModel):
             return instances

         self.objstore = ObjectStore(objstore_loc or config.get_object_store())
+        self.events = LibvirtEvents()
         self.conn = LibvirtConnection(libvirt_uri)
-        kargs = {'objstore': self.objstore, 'conn': self.conn}
+        self.events.register_common_events(self.conn)
+        kargs = {'objstore': self.objstore, 'conn': self.conn,
+                 'eventsloop': self.events}
         models = []

         # Import task model from Wok
--
2.5.0




More information about the Kimchi-devel mailing list