[PATCH 0 of 2] [TEST] Adding new tc for verifying Migration indication for KVM.

Moved the indications related to fns to new lib indications.py. Removed some un necessary import stmts

# HG changeset patch # User Deepti B.Kalakeri <deeptik@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@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@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

Deepti B. Kalakeri wrote:
# HG changeset patch # User Deepti B.Kalakeri <deeptik@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.
Oops, I think I was unclear in my previous mail. I think the indication tester should stay intact... The reason we decided to copy the indication_tester from libcmpiutil to cimtest is so that in bugs that get fixed in one get fixed in the other. That's why they need to stay in sync. So, if you find a bug in filter_xml(), you want to be sure its fixed in both places. The problem was that cimtest wasn't publicly available at the time, and indications aren't trivial to test using standard CIM related tools. So we wanted to offer users a way to test their indications, which is why it exists in libcmpiutil. We could remove the indication_tester.py from libcmpiutil and leave the only copy in cimtest, however, I think we should have two copies of the same code in cimtest. So, I suggest leave indication_tester.py as is and place the functions below in their own file. Does that seem reasonable? That way, we don't duplicate code - if we fix a bug in one spot, we won't have to fix the same bug somewhere else.
+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
-- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

Kaitlin Rupert wrote:
Deepti B. Kalakeri wrote:
# HG changeset patch # User Deepti B.Kalakeri <deeptik@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.
Oops, I think I was unclear in my previous mail. I think the indication tester should stay intact... The reason we decided to copy the indication_tester from libcmpiutil to cimtest is so that in bugs that get fixed in one get fixed in the other. That's why they need to stay in sync.
So, if you find a bug in filter_xml(), you want to be sure its fixed in both places. The problem was that cimtest wasn't publicly available at the time, and indications aren't trivial to test using standard CIM related tools. So we wanted to offer users a way to test their indications, which is why it exists in libcmpiutil.
We could remove the indication_tester.py from libcmpiutil and leave the only copy in cimtest, however, I think we should have two copies of the same code in cimtest. I guess you meant to say "I think we not should have two copies" ???
So, I suggest leave indication_tester.py as is and place the functions below in their own file. Does that seem reasonable? That way, we don't duplicate code - if we fix a bug in one spot, we won't have to fix the same bug somewhere else. ok sure. done..
+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
-- Thanks and Regards, Deepti B. Kalakeri IBM Linux Technology Center deeptik@linux.vnet.ibm.com

We could remove the indication_tester.py from libcmpiutil and leave the only copy in cimtest, however, I think we should have two copies of the same code in cimtest.
I guess you meant to say "I think we not should have two copies" ???
Ah, yes - that's where the confusion came in. My apologies for the typo here. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

# HG changeset patch # User Deepti B.Kalakeri <deeptik@linux.vnet.ibm.com> # Date 1247144016 25200 # Node ID 246937db436f15084972c0afb787666faf1280e9 # Parent 73aedcd4026381023be4d25d741ce74113b8f8e6 [TEST] Adding new tc to verify Migration indications for KVM. Tested with KVM and current sources on F10. Signed-off-by: Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> diff -r 73aedcd40263 -r 246937db436f suites/libvirt-cim/cimtest/ComputerSystemMigrationJobIndication/01_csmig_ind_for_offline_mig.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/suites/libvirt-cim/cimtest/ComputerSystemMigrationJobIndication/01_csmig_ind_for_offline_mig.py Thu Jul 09 05:53:36 2009 -0700 @@ -0,0 +1,195 @@ +#!/usr/bin/python +# +# Copyright 2009 IBM Corp. +# +# Authors: +# Deepti B. Kalakeri <deeptik@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 +# +# +# This testcase is used to verify the Created|Modified|Deleted +# Migration Indications for offline VM Migration. +# +# Date : 06-07-2009 +# + +import sys +from signal import SIGKILL +from socket import gethostname +from os import kill, fork, _exit +from XenKvmLib.vxml import get_class +from XenKvmLib.xm_virt_util import domain_list, net_list +from CimTest.Globals import logger +from XenKvmLib.const import do_main, default_network_name +from CimTest.ReturnCodes import PASS, FAIL +from XenKvmLib.vsmigrations import check_mig_support, local_remote_migrate +from XenKvmLib.common_util import poll_for_state_change, create_netpool_conf,\ + destroy_netpool +from XenKvmLib.indications import sub_ind, handle_request, poll_for_ind + +sup_types = ['KVM', 'Xen'] + +REQUESTED_STATE = 3 + +def setup_guest(test_dom, ip, virt): + virt_xml = get_class(virt) + cxml = virt_xml(test_dom) + ret = cxml.cim_define(ip) + if not ret: + logger.error("Error define domain %s", test_dom) + return FAIL, cxml + + status, dom_cs = poll_for_state_change(ip, virt, test_dom, + REQUESTED_STATE) + if status != PASS: + cxml.undefine(test_dom) + logger.error("'%s' didn't change state as expected" % test_dom) + return FAIL, cxml + + return PASS, cxml + +def cleanup_guest_netpool(virt, cxml, test_dom, t_sysname, + s_sysname, clean_net=True): + # Clean the domain on target machine. + # This is req when migration is successful, also when migration is not + # completely successful VM might be created on the target machine + # and hence need to clean. + target_list = domain_list(t_sysname, virt) + if target_list != None and test_dom in target_list: + ret_value = cxml.undefine(t_sysname) + if not ret_value: + logger.info("Failed to undefine the migrated domain '%s' on '%s'", + test_dom, t_sysname) + + if clean_net != True: + return + + # clean the networkpool created on the remote machine + target_net_list = net_list(t_sysname, virt) + if target_net_list != None and default_network_name in target_net_list: + ret_value = destroy_netpool(t_sysname, virt, default_network_name) + if ret_value != PASS: + logger.info("Unable to destroy networkpool '%s' on '%s'", + default_network_name, t_sysname) + + # Remote Migration not Successful, clean the domain on src machine + src_list = domain_list(s_sysname, virt) + if src_list != None and test_dom in src_list: + ret_value = cxml.undefine(s_sysname) + if not ret_value: + logger.info("Failed to undefine the domain '%s' on source '%s'", + test_dom, s_sysname) + + +def gen_indication(test_dom, s_sysname, virt, t_sysname): + cxml = None + try: + status, cxml = setup_guest(test_dom, s_sysname, virt) + if status != PASS: + logger.error("Error setting up the guest") + return status, None + + # create the networkpool used in the domain to be migrated + # on the target machine. + t_net_list = net_list(t_sysname, virt) + if t_net_list != None and default_network_name not in t_net_list: + status, netpool = create_netpool_conf(t_sysname, virt, + net_name=default_network_name) + if status != PASS: + raise Exception("Unable to create network pool '%s' on '%s'" + % (default_network_name, t_sysname)) + + # Migrate the test_dom to t_sysname. + # Enable remote migration by setting remote_migrate=1 + status = local_remote_migrate(s_sysname, t_sysname, virt, + remote_migrate=1, + guest_name=test_dom, + mtype='offline') + + except Exception, details: + logger.error("Exception details :%s", details) + return FAIL, cxml + + return status, cxml + +@do_main(sup_types) +def main(): + options = main.options + virt = options.virt + status, s_sysname, t_sysname = check_mig_support(virt, options) + if status != PASS: + return status + + status = FAIL + test_dom = 'VM_frm_' + gethostname() + ind_names = { + 'create' : 'ComputerSystemMigrationJobCreatedIndication', + 'modify' : 'ComputerSystemMigrationJobModifiedIndication', + 'delete' : 'ComputerSystemMigrationJobDeletedIndication' + } + + sub_list, ind_names, dict = sub_ind(s_sysname, virt, ind_names) + for ind in ind_names.keys(): + sub = sub_list[ind] + ind_name = ind_names[ind] + logger.info("\n Verifying '%s' indications ....", ind_name) + try: + pid = fork() + if pid == 0: + status = handle_request(sub, ind_name, dict, + len(ind_names.keys())) + if status != PASS: + _exit(1) + + _exit(0) + else: + try: + status, cxml = gen_indication(test_dom, s_sysname, + virt, t_sysname) + if status != PASS: + kill(pid, SIGKILL) + raise Exception("Unable to generate indication") + + status = poll_for_ind(pid, ind_name) + except Exception, details: + kill(pid, SIGKILL) + raise Exception(details) + + except Exception, details: + logger.error("Exception: %s", details) + status = FAIL + + if status != PASS: + break + + cleanup_guest_netpool(virt, cxml, test_dom, t_sysname, + s_sysname, clean_net=False) + + + #Make sure all subscriptions are really unsubscribed + for ind, sub in sub_list.iteritems(): + sub.unsubscribe(dict['default_auth']) + logger.info("Cancelling subscription for %s", ind_names[ind]) + + cleanup_guest_netpool(virt, cxml, test_dom, t_sysname, + s_sysname) + return status + + +if __name__ == "__main__": + sys.exit(main()) +
participants (3)
-
Deepti B Kalakeri
-
Deepti B. Kalakeri
-
Kaitlin Rupert