[libvirt] [libvirt-test-API][PATCH 1/2] Add test case for network event callback

Jincheng Miao jmiao at redhat.com
Sun Feb 15 07:02:10 UTC 2015


Signed-off-by: Jincheng Miao <jmiao at redhat.com>
---
 repos/network/event_callback.py |  245 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 245 insertions(+), 0 deletions(-)
 create mode 100644 repos/network/event_callback.py

diff --git a/repos/network/event_callback.py b/repos/network/event_callback.py
new file mode 100644
index 0000000..c4c2b61
--- /dev/null
+++ b/repos/network/event_callback.py
@@ -0,0 +1,245 @@
+#!/usr/bin/python
+import time
+import threading
+
+import libvirt
+from libvirt import libvirtError
+from src import sharedmod
+
+
+required_params = ('action',)
+optional_params = {'networkname' : 'testnetcb',
+                   'bridgename' : 'testnetcbbr',
+                   'bridgeip' : '192.168.123.1',
+                   'bridgenetmask' : '255.255.255.0',
+                   'netstart' : '192.168.123.2',
+                   'netend' : '192.168.123.254',
+                   'netmode' : 'nat',
+                   'xml' : 'xmls/network.xml',
+                  }
+
+def net_define(conn, net_name, xmlstr):
+    """ define a network
+    """
+    conn.networkDefineXML(xmlstr)
+
+def net_undefine(conn, net_name, xmlstr):
+    """ undefine a network
+    """
+    netobj = conn.networkLookupByName(net_name)
+    netobj.undefine()
+
+def net_start(conn, net_name, xmlstr):
+    """ start a network
+    """
+    try:
+        netobj = conn.networkLookupByName(net_name)
+        netobj.create()
+    except libvirtError:
+        conn.networkCreateXML(xmlstr)
+    
+
+def net_destroy(conn, net_name, xmlstr):
+    """ destroy a network
+    """
+    netobj = conn.networkLookupByName(net_name)
+    netobj.destroy()
+
+event_func_map = {"define"      : net_define,
+                  "undefine"    : net_undefine,
+                  "start"       : net_start,
+                  "destroy"     : net_destroy,
+                  }
+
+def net_str_to_func(action):
+    """ convert string to net function
+    """
+    return event_func_map[action]
+
+class event_loop(object):
+    def __init__(self):
+        self._thread = None
+        self.running = False
+
+    def __del__(self):
+        self._thread = None
+        self.running = False
+
+    def _event_loop_native(self):
+        while self.running:
+            libvirt.virEventRunDefaultImpl()
+
+    def start(self):
+        """ start event loop by spawning a new thread
+        """
+        libvirt.virEventRegisterDefaultImpl()
+        self.running = True
+        self._thread = threading.Thread(target=self._event_loop_native,
+                                       name="libvirtEventLoop")
+        self._thread.setDaemon(True)
+        self._thread.start()
+
+    def wait(self, timeout=None):
+        self._thread.join(timeout)
+
+class event_lifecycle_callback(object):
+    def __init__(self, net_name, action):
+        self._net_name = net_name
+        self._action = action
+        self.callback_id = None
+        self.finished = False
+
+    def __del__(self):
+        self._net_name = None
+        self._action = None
+        self.callback_id = None
+        self.finished = False
+
+    def _net_event_str(self, event):
+        netEventStrings = ( "define",
+                            "undefine",
+                            "start",
+                            "destroy",
+                            )
+        return netEventStrings[event]
+
+    def callback_func(self, conn, net, event, detail, opaque):
+        """ the callback function implement
+        """
+        if net.name() == self._net_name and \
+                self._net_event_str(event) == self._action:
+            self.finished = True
+
+class event_trigger(object):
+    def __init__(self, conn, args):
+        self._conn = conn
+        self._net = args[0]
+        self._xmlstr = args[1]
+        self._action = args[2]
+        self._thread = None
+        self.fin_event = threading.Event()
+
+    def __del__(self):
+        self.fin_event.clear()
+        self._thread = None
+        self._conn = None
+        self._net = None
+        self._xmlstr = None
+        self._action = None
+
+    def _thread_func(self, conn, action, net_name, xmlstr):
+        net_str_to_func(action)(conn, net_name, xmlstr)
+        self.fin_event.set()
+
+    def start(self):
+        """ start to trigger an event by spawning a new thread
+        """
+        self._thread = threading.Thread(target=self._thread_func,
+                                        args=(self._conn, self._action,
+                                              self._net, self._xmlstr))
+        self._thread.setDaemon(True)
+        self._thread.start()
+
+def check_event_callback(callback, logger):
+    """ check event callback result, returns True if success,
+        or False if timeout. threading.Event.wait() always return None in
+        python2.6, for compatibilities we implement timeout mechanism.
+    """
+    counter = 60
+    while not callback.finished:
+        time.sleep(1)
+        counter -= 1
+        if counter < 0:
+            logger.error("event callback checking time out")
+            return False
+
+    return True
+
+def event_callback(params):
+    """ test event callback
+        it expects virtual network started while testing destroy callback,
+        defined while testing undefined callback, verse vice.
+    """
+    logger = params['logger']
+    xmlstr = params['xml']
+    action = params['action']
+    net_name = params.get('networkname', 'testnetcb')
+    event_id = libvirt.VIR_NETWORK_EVENT_ID_LIFECYCLE
+    started = False
+    defined = False
+    ret = 1
+
+    conn = sharedmod.libvirtobj['conn']
+    logger.info("begin to %s network: %s" % (action, net_name))
+
+    if not action in event_func_map:
+        logger.error("wrong action specified: %s" % action)
+        return 1
+
+    # detect if the target net is active
+    for n in conn.listAllNetworks(2):
+        if n.name() == net_name:
+            started = True
+
+    # detect if the target net is defined
+    for n in conn.listAllNetworks(4):
+        if n.name() == net_name:
+            defined = True
+
+    if action == 'destroy':
+        if not started:
+            logger.error("the virtual network %s is not active" % net_name)
+            return 1
+    elif action == 'undefine':
+        if not defined:
+            logger.error("the virtual network %s is not defined" % net_name)
+            return 1
+    elif action == 'define':
+        if defined:
+            logger.error("the virtual network %s is defined" % net_name)
+            return 1
+    else:
+        if started:
+            logger.error("the virtual network %s is started" % net_name)
+            return 1
+
+    # start event loop
+    el = event_loop()
+    el.start()
+
+    # re-fetch the connection
+    conn = libvirt.open()
+
+    ec = event_lifecycle_callback(net_name, action)
+    # register event callback
+    try:
+        ec.callback_id = conn.networkEventRegisterAny(None, event_id,
+                                                      ec.callback_func, None)
+    except libvirtError, e:
+        logger.error("API error message: %s, error code is %s" %
+                     (e.message, e.get_error_code()))
+        logger.error("fail to destroy domain")
+        # unregister callback
+        conn.networkEventDeregisterAny(ec.callback_id)
+        el.running = False
+        el.wait(60)
+        return 1
+
+    # do action for network in child thread, always before main thread
+    args = [net_name, xmlstr, action]
+    et = event_trigger(conn, args)
+    et.start()
+
+    # wait for event_tigger finished
+    et.fin_event.wait(60)
+
+    if check_event_callback(ec, logger):
+        logger.info("event callback on %s's %s: pass" % (net_name, action))
+        ret = 0
+    else:
+        logger.error("event callback on %s's %s: fail" % (net_name, action))
+
+    conn.networkEventDeregisterAny(ec.callback_id)
+    el.running = False
+    el.wait(60)
+    return ret
-- 
1.7.1




More information about the libvir-list mailing list