[Libvirt-cim] [PATCH 1 of 2] [TEST] Added the indications.py to support Indications

Deepti B. Kalakeri deeptik at linux.vnet.ibm.com
Thu Jul 9 12:55:37 UTC 2009


# HG changeset patch
# User Deepti B.Kalakeri <deeptik at linux.vnet.ibm.com>
# Date 1247143660 25200
# Node ID 73aedcd4026381023be4d25d741ce74113b8f8e6
# Parent  7b18b827fca6916fd87ff417f79a96c8a19b4913
[TEST] Added the indications.py to support Indications.

Included the following important functions in indications.py
    - sub_ind()        --> Subscribe for the indications to be watched.
    - handle_request() --> Filters the required indications.
    - poll_for_ind()   --> Wait for the required indications to be triggered.

Tested with KVM and current sources on F10.
Signed-off-by: Deepti B. Kalakeri <deeptik at linux.vnet.ibm.com>

diff -r 7b18b827fca6 -r 73aedcd40263 suites/libvirt-cim/lib/XenKvmLib/indications.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/suites/libvirt-cim/lib/XenKvmLib/indications.py	Thu Jul 09 05:47:40 2009 -0700
@@ -0,0 +1,461 @@
+#!/usr/bin/python
+#
+# Copyright 2009 IBM Corp.
+#
+# Authors:
+#    Deepti B. Kalakeri <deeptik at linux.vnet.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+#
+#
+
+import httplib
+import base64
+import BaseHTTPServer
+from xml.dom.minidom import parseString
+from signal import SIGKILL
+from CimTest.Globals import logger
+from XenKvmLib.vxml import set_default
+from XenKvmLib.classes import get_typed_class
+from CimTest.ReturnCodes import PASS, FAIL
+from os import waitpid, kill, WNOHANG
+
+def filter_xml(name, type, ns, sysname):
+    return """
+    <?xml version="1.0" encoding="utf-8"?> 
+    <CIM CIMVERSION="2.0" DTDVERSION="2.0"> 
+    <MESSAGE ID="4711" PROTOCOLVERSION="1.0"> 
+      <SIMPLEREQ> 
+        <IMETHODCALL NAME="CreateInstance"> 
+          <LOCALNAMESPACEPATH> 
+            <NAMESPACE NAME="root"/> 
+            <NAMESPACE NAME="PG_InterOp"/> 
+          </LOCALNAMESPACEPATH> 
+          <IPARAMVALUE NAME="NewInstance"> 
+              <INSTANCE CLASSNAME="CIM_IndicationFilter">
+                <PROPERTY NAME="SystemCreationClassName" TYPE="string"> 
+                  <VALUE>CIM_ComputerSystem</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="SystemName" TYPE="string"> 
+                  <VALUE>%s</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="CreationClassName" TYPE="string"> 
+                  <VALUE>CIM_IndicationFilter</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="Name" TYPE="string"> 
+                  <VALUE>%sFilter</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="Query" TYPE="string"> 
+                  <VALUE> SELECT * FROM %s 
+                  </VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="QueryLanguage" TYPE="string"> 
+                  <VALUE>WQL</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="SourceNamespace" TYPE="string"> 
+                  <VALUE>%s</VALUE> 
+                </PROPERTY> 
+              </INSTANCE> 
+            </IPARAMVALUE> 
+          </IMETHODCALL> 
+        </SIMPLEREQ> 
+      </MESSAGE> 
+    </CIM>
+    """ % (sysname, name, type, ns)
+
+def handler_xml(name, port, sysname):
+    return """
+    <?xml version="1.0" encoding="utf-8"?> 
+    <CIM CIMVERSION="2.0" DTDVERSION="2.0"> 
+      <MESSAGE ID="4711" PROTOCOLVERSION="1.0"> 
+        <SIMPLEREQ> 
+        <IMETHODCALL NAME="CreateInstance"> 
+            <LOCALNAMESPACEPATH> 
+              <NAMESPACE NAME="root"/> 
+              <NAMESPACE NAME="PG_InterOp"/> 
+            </LOCALNAMESPACEPATH> 
+            <IPARAMVALUE NAME="NewInstance"> 
+              <INSTANCE CLASSNAME="CIM_IndicationHandlerCIMXML"> 
+                <PROPERTY NAME="SystemCreationClassName" TYPE="string"> 
+                  <VALUE>CIM_ComputerSystem</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="SystemName" TYPE="string"> 
+                  <VALUE>%s</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="CreationClassName" TYPE="string"> 
+                  <VALUE>CIM_IndicationHandlerCIMXML</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="Name" TYPE="string"> 
+                  <VALUE>%sHandler</VALUE> 
+                </PROPERTY> 
+                <PROPERTY NAME="Destination" TYPE="string"> 
+                  <VALUE>http://localhost:%i</VALUE> 
+                </PROPERTY> 
+              </INSTANCE> 
+            </IPARAMVALUE> 
+          </IMETHODCALL> 
+        </SIMPLEREQ> 
+      </MESSAGE> 
+      </CIM>
+      """ % (sysname, name, port)
+
+def subscription_xml(name, sysname):
+    return """
+    <?xml version="1.0" encoding="utf-8"?> 
+    <CIM CIMVERSION="2.0" DTDVERSION="2.0"> 
+      <MESSAGE ID="4711" PROTOCOLVERSION="1.0"> 
+        <SIMPLEREQ> 
+          <IMETHODCALL NAME="CreateInstance"> 
+            <LOCALNAMESPACEPATH> 
+              <NAMESPACE NAME="root"/> 
+              <NAMESPACE NAME="PG_InterOp"/> 
+            </LOCALNAMESPACEPATH> 
+            <IPARAMVALUE NAME="NewInstance"> 
+              <INSTANCE CLASSNAME="CIM_IndicationSubscription"> 
+                <PROPERTY.REFERENCE NAME="Filter" 
+                                    REFERENCECLASS="CIM_IndicationFilter"> 
+                  <VALUE.REFERENCE> 
+                    <INSTANCENAME CLASSNAME="CIM_IndicationFilter"> 
+                      <KEYBINDING NAME="SystemCreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_ComputerSystem 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="SystemName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %s 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="CreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_IndicationFilter 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="Name"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %sFilter 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                    </INSTANCENAME> 
+                  </VALUE.REFERENCE> 
+                </PROPERTY.REFERENCE> 
+                <PROPERTY.REFERENCE NAME="Handler" 
+                                    REFERENCECLASS="CIM_IndicationHandler"> 
+                  <VALUE.REFERENCE> 
+                    <INSTANCENAME CLASSNAME="CIM_IndicationHandlerCIMXML"> 
+                      <KEYBINDING NAME="SystemCreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_ComputerSystem 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="SystemName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %s
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="CreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_IndicationHandlerCIMXML 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="Name"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %sHandler 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                    </INSTANCENAME> 
+                  </VALUE.REFERENCE> 
+                </PROPERTY.REFERENCE> 
+                <PROPERTY NAME="SubscriptionState" TYPE="uint16"> 
+                  <VALUE> 2 </VALUE> 
+                </PROPERTY> 
+              </INSTANCE> 
+            </IPARAMVALUE> 
+          </IMETHODCALL> 
+        </SIMPLEREQ> 
+      </MESSAGE> 
+      </CIM>
+      """ % (sysname, name, sysname, name)
+
+def delete_inst_xml(name, type, sysname, inst_name):
+    return """
+    <?xml version="1.0" encoding="utf-8"?> 
+    <CIM CIMVERSION="2.0" DTDVERSION="2.0"> 
+      <MESSAGE ID="4711" PROTOCOLVERSION="1.0"> 
+        <SIMPLEREQ> 
+          <IMETHODCALL NAME="DeleteInstance"> 
+            <LOCALNAMESPACEPATH> 
+              <NAMESPACE NAME="root"/> 
+              <NAMESPACE NAME="PG_InterOp"/> 
+            </LOCALNAMESPACEPATH> 
+            <IPARAMVALUE NAME="InstanceName"> 
+              <INSTANCENAME CLASSNAME="CIM_Indication%s"> 
+                <KEYBINDING NAME="SystemCreationClassName"> 
+                  <KEYVALUE>CIM_ComputerSystem</KEYVALUE> 
+                </KEYBINDING> 
+                <KEYBINDING NAME="SystemName"> 
+                  <KEYVALUE>%s</KEYVALUE> 
+                </KEYBINDING> 
+                <KEYBINDING NAME="CreationClassName"> 
+                  <KEYVALUE>CIM_Indication%s</KEYVALUE> 
+                </KEYBINDING> 
+                <KEYBINDING NAME="Name"> 
+                  <KEYVALUE>%s</KEYVALUE> 
+                </KEYBINDING> 
+              </INSTANCENAME> 
+            </IPARAMVALUE> 
+          </IMETHODCALL> 
+        </SIMPLEREQ> 
+      </MESSAGE> 
+    </CIM>;
+    """ % (type, sysname, type, inst_name);
+
+def delete_sub_xml(name, sysname):
+    return """
+    <?xml version="1.0" encoding="utf-8"?> 
+    <CIM CIMVERSION="2.0" DTDVERSION="2.0"> 
+      <MESSAGE ID="4711" PROTOCOLVERSION="1.0"> 
+        <SIMPLEREQ> 
+          <IMETHODCALL NAME="DeleteInstance"> 
+            <LOCALNAMESPACEPATH> 
+              <NAMESPACE NAME="root"/> 
+              <NAMESPACE NAME="PG_InterOp"/> 
+            </LOCALNAMESPACEPATH> 
+            <IPARAMVALUE NAME="InstanceName"> 
+              <INSTANCENAME CLASSNAME="CIM_IndicationSubscription"> 
+                <KEYBINDING NAME="Filter"> 
+                  <VALUE.REFERENCE> 
+                    <INSTANCENAME CLASSNAME="CIM_IndicationFilter"> 
+                      <KEYBINDING NAME="SystemCreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_ComputerSystem 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="SystemName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %s
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="CreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_IndicationFilter 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="Name"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %sFilter 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                    </INSTANCENAME> 
+                  </VALUE.REFERENCE> 
+                </KEYBINDING> 
+                <KEYBINDING NAME="Handler"> 
+                  <VALUE.REFERENCE> 
+                    <INSTANCENAME CLASSNAME="CIM_IndicationHandlerCIMXML"> 
+                      <KEYBINDING NAME="SystemCreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_ComputerSystem 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="SystemName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %s
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="CreationClassName"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        CIM_IndicationHandlerCIMXML 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                      <KEYBINDING NAME="Name"> 
+                        <KEYVALUE VALUETYPE="string"> 
+                        %sHandler 
+                        </KEYVALUE> 
+                      </KEYBINDING> 
+                    </INSTANCENAME> 
+                  </VALUE.REFERENCE> 
+                </KEYBINDING> 
+              </INSTANCENAME> 
+            </IPARAMVALUE> 
+          </IMETHODCALL> 
+        </SIMPLEREQ> 
+      </MESSAGE> 
+    </CIM>;
+    """ % (sysname, name, sysname, name)
+
+class CIMIndication:
+    def __init__(self, xmldata):
+        dom = parseString(xmldata)
+
+        instances = dom.getElementsByTagName("INSTANCE")
+        attrs = instances[0].attributes.items()
+        self.name = attrs[0][1]
+
+    def __str__(self):
+        return self.name
+
+class CIMSocketHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+    def do_POST(self):
+        length = self.headers.getheader('content-length')
+        data = self.rfile.read(int(length))
+
+        indication = CIMIndication(data)
+        print "Got indication: %s" % indication
+        if self.server.print_ind:
+            print "%s\n\n" % data
+        self.server.indications.append(indication)
+
+class CIMIndicationSubscription:
+    def __init__(self, name, typ, ns, print_ind, sysname, port=0):
+        self.name = name
+        self.type = typ
+        self.ns = ns
+        self.sysname = sysname
+
+        self.port = 8000 + port 
+        self.server = BaseHTTPServer.HTTPServer(('', self.port), 
+                                                 CIMSocketHandler)
+        self.server.print_ind = print_ind
+        self.server.indications = []
+
+        self.filter_xml = filter_xml(name, typ, ns, sysname)
+        self.handler_xml = handler_xml(name, self.port, sysname)
+        self.subscription_xml = subscription_xml(name, sysname)
+
+    def __do_cimpost(self, conn, body, method, auth_hdr=None):
+        headers = {"CIMOperation" : "MethodCall",
+                   "CIMMethod"    : method,
+                   "CIMObject"    : "root/PG_Interop",
+                   "Content-Type" : 'application/xml; charset="utf-8"'}
+ 
+        if auth_hdr:
+            headers["Authorization"] = "Basic %s" % auth_hdr
+
+        conn.request("POST", "/cimom", body, headers)
+        resp = conn.getresponse()
+        if not resp.getheader("content-length"):
+            raise Exception("Request Failed: %d %s" % 
+                            (resp.status, resp.reason))
+
+        resp.read()
+
+    def subscribe(self, url, cred=None):
+        self.conn = httplib.HTTPConnection(url)
+        if cred:
+            (u, p) = cred
+            auth_hdr = base64.b64encode("%s:%s" % (u, p))
+        else:
+            auth_hdr = None
+
+        self.__do_cimpost(self.conn, self.filter_xml,
+                          "CreateInstance", auth_hdr)
+        self.__do_cimpost(self.conn, self.handler_xml,
+                          "CreateInstance", auth_hdr)
+        self.__do_cimpost(self.conn, self.subscription_xml,
+                          "CreateInstance", auth_hdr)
+
+    def unsubscribe(self, cred=None):
+        if cred:
+            (u, p) = cred
+            auth_hdr = base64.b64encode("%s:%s" % (u, p))
+        else:
+            auth_hdr = None
+
+        xml = delete_sub_xml(self.name, self.sysname)
+        self.__do_cimpost(self.conn, xml,
+                          "DeleteInstance", auth_hdr)
+        xml = delete_inst_xml(self.name, "HandlerCIMXML", self.sysname,
+                              "%sHandler" % self.name)
+        self.__do_cimpost(self.conn, xml,
+                          "DeleteInstance", auth_hdr)
+        xml = delete_inst_xml(self.name, "Filter", self.sysname,
+                              "%sFilter" % self.name)
+        self.__do_cimpost(self.conn, xml,
+                          "DeleteInstance", auth_hdr)
+
+
+def sub_ind(ip, virt, ind_names):
+    dict = set_default(ip)
+    sub_list = {}
+    port = 5
+
+    for ind, iname in ind_names.iteritems():
+        ind_name = get_typed_class(virt, iname)
+
+        sub_name = "Test%s" % ind_name
+        port += 1
+
+        sub = CIMIndicationSubscription(sub_name, ind_name,
+                                        dict['default_ns'],
+                                        dict['default_print_ind'],
+                                        dict['default_sysname'],
+                                        port)
+        sub.subscribe(dict['default_url'], dict['default_auth'])
+        logger.info("Watching for %s", iname)
+        ind_names[ind] = ind_name
+        sub_list[ind] = sub
+
+    return sub_list, ind_names, dict
+
+def handle_request(sub, ind_name, dict, exp_ind_ct):
+    #sfcb delivers indications to all registrations, even if the indication
+    #isn't what the registration was subscribed to.  So, for modified and 
+    #deleted indications, we must loop through until the indication we are
+    #looking for is triggered.
+    for i in range(0, exp_ind_ct):
+        sub.server.handle_request() 
+        if len(sub.server.indications) < 1:
+            logger.error("No valid indications received")
+            return FAIL
+
+        if str(sub.server.indications[0]) == ind_name:
+                sub.unsubscribe(dict['default_auth'])
+                logger.info("Cancelling subscription for %s", ind_name)
+                return PASS
+        else:
+                sub.server.indications.remove(sub.server.indications[0])
+
+    logger.error("Did not recieve indication %s", ind_name)
+    return FAIL
+
+def poll_for_ind(pid, ind_name, timeout=20):
+    status = FAIL
+    for i in range(0, timeout):
+        pw = waitpid(pid, WNOHANG)
+
+        # If pid exits, waitpid returns [pid, return_code] 
+        # If pid is still running, waitpid returns [0, 0]
+        # Only return a success if waitpid returns the expected pid
+        # and the return code is 0.
+        if pw[0] == pid and pw[1] == 0:
+            logger.info("Great, got '%s' indication successfully", ind_name)
+            status = PASS
+            break
+        elif pw[1] == 0 and i < timeout:
+            if i % 10 == 0:
+                logger.info("In child, waiting for '%s' indication", ind_name)
+            sleep(1)
+        else:
+            # Time is up and waitpid never returned the expected pid
+            if pw[0] != pid:
+                logger.error("Waited too long for '%s' indication", ind_name)
+                kill(pid, SIGKILL)
+            else:
+                logger.error("Received Indication error: '%d'", pw[1])
+
+            status = FAIL
+            break
+
+    return status




More information about the Libvirt-cim mailing list