[Libvirt-cim] cimtest - add SSL support to indication_tester.py
Dave Heller
deheller at ptd.net
Wed Mar 21 17:00:03 UTC 2012
Sorry for the delay. Yes, I will do that and re-post the patch.
> -----Original Message-----
> From: libvirt-cim-bounces at redhat.com [mailto:libvirt-cim-
> bounces at redhat.com] On Behalf Of Sharad Mishra
> Sent: Tuesday, March 20, 2012 1:37 PM
> To: List for discussion and development of libvirt CIM
> Subject: Re: [Libvirt-cim] cimtest - add SSL support to
> indication_tester.py
>
> On Mon, 2012-03-19 at 19:41 -0400, Dave Heller wrote:
> > Hi Sharad,
> >
> > Actually, I did modify the script in a way that it is still compatible
> with
> > cimtest (based on tests using ComputerSystemIndication
>
> In that case, I am going to apply your patch and test as update to
> existing indication script.
>
> > 01_created_indication). But if you think it makes sense to fork it to a
> > standalone script (and rename it), that is fine too.
> >
> > The usage of the script as I intend is interactive from the command
> line. I
> > can add some documentation with example commands. Is there a standard
> place
> > this should go, or should I add a README?
>
> You can add it to the script header itself.
> Do you want to send another patch with usage added and "orig" removed
> from the file name?
>
> Regards,
> Sharad Mishra
>
> >
> > Thanks,
> > Dave
> >
> > > -----Original Message-----
> > > From: libvirt-cim-bounces at redhat.com [mailto:libvirt-cim-
> > > bounces at redhat.com] On Behalf Of Sharad Mishra
> > > Sent: Monday, March 19, 2012 5:40 PM
> > > To: List for discussion and development of libvirt CIM
> > > Subject: Re: [Libvirt-cim] cimtest - add SSL support to
> > > indication_tester.py
> > >
> > > Dave,
> > >
> > > I assume that this patch is not going to be applied to the existing
> > > indication_tester.py in cimtest. In that case, we can add this
> modified
> > > indication_tester.py as a new file at the same location as current
> > > indication_tester.py. We do need to give this script a new name. This
> > > script is currently not used/invoked by any existing cimtests. Do you
> > > want to write tests to use this script?
> > >
> > > Regards
> > > Sharad Mishra
> > >
> > > On Mon, 2012-03-19 at 13:21 -0400, Dave Heller wrote:
> > > > In the XenKvmLib directory in cimtest, there is a
> "indication_tester.py"
> > > > module that is both a command-line program and a component of
> cimtest.
> > > Here
> > > > is a proposed patch that adds new functionality to the cmdline
> interface
> > > > while preserving compatibility with cimtest.
> > > >
> > > > The most significant new feature is support for SSL indications.
> There
> > > is
> > > > also a new --trigger mode to generate a test indication using the
> SFCB
> > > > Test_Indication provider. This allows the script to act as a
> completely
> > > > stand-alone test tool (for SFCB) without the user having to rely on
> the
> > > > "xmltest" files and wbemcat.
> > > >
> > > > Below is a complete list of the new features. I am looking for
> feedback
> > > and
> > > > potentially, the correct process to check into "cimtest".
> > > >
> > > > Best regards,
> > > > Dave Heller
> > > >
> > > > New features:
> > > >
> > > > - Supports https indications. Adds new options --certFile and --
> keyFile
> > > to
> > > > specify server certificate and private key for the SSL enabled
> > > indication
> > > > listener.
> > > > - Supports verification of indication sender (i.e. CIMOM) SSL
> > > certificate.
> > > > New option --trustStore is used to specify the CA certificate file;
> > > > alternately the --noverify option may be used to disable peer
> > > certificate
> > > > checking.
> > > > - Adds new option --dest to specify handler destination. This same
> URL
> > > is
> > > > used to register the subscription (at the CIMOM) and start the
> > > indication
> > > > listener (locally). Via --dest one can specify scheme (http or
> https),
> > > IP or
> > > > hostname, listener port, and optionally userid:password, all in a
> single
> > > > parameter.
> > > > - New option --interop can be used to override the default interop
> > > namespace
> > > > (i.e root/interop vs. root/PG_InterOp) allowing easy support for
> both
> > > > openpegasus and sfcb.
> > > > - Modifies the default value of existing --ns option (indication
> > > namespace);
> > > > if not specified the indication namespace will default to the same
> value
> > > as
> > > > the interop namespace.
> > > > - New option --verbose can be used to display debugging info, such
> as
> > > > details (subject, issuer) of the indication sender cert (when peer
> > > > verification enabled).
> > > > - Improved error handling (i.e. catch exceptions) for the following
> > > > operations: starting listener locally, receiving incoming
> indications,
> > > POST
> > > > operations (i.e. subscribe, unsubscribe) to CIMOM.
> > > > - New option --trigger can be used to send a request to CIMOM to
> trigger
> > > an
> > > > indication via the SFCB Test_Indication provider.
> > > >
> > > > Limitations:
> > > >
> > > > - Not tested on IPv6.
> > > > - The --trigger option currently only supports the sfcb
> Test_Indication
> > > > provider. (It could be made more general by allowing the XML send
> to
> > > > support an arbitrary namespace, classname and method call. Open to
> > > > suggestions here.)
> > > >
> > > >
> > > > --- indication_tester.orig.py 2012-03-05 23:12:08.000000000 -0500
> > > > +++ indication_tester.py 2012-03-19 13:12:55.000000000 -0400
> > > > @@ -1,18 +1,25 @@
> > > > #!/usr/bin/python
> > > > -# Copyright IBM Corp. 2007
> > > > +# Copyright IBM Corp. 2007-2012
> > > > #
> > > > # indication_tester.py - Tool for testing indication subscription
> and
> > > > # delivery against a CIMOM
> > > > # Author: Dan Smith <danms at us.ibm.com>
> > > > +# SSL support added by Dave Heller <hellerda at us.ibm.com>
> > > >
> > > > import sys
> > > > from optparse import OptionParser
> > > > -import BaseHTTPServer
> > > > +from urlparse import urlparse, urlunparse
> > > > +from xml.dom.minidom import parse, parseString
> > > > import httplib
> > > > import base64
> > > > -from xml.dom.minidom import parse, parseString
> > > > +import errno, os, re
> > > > +import socket
> > > > +from SocketServer import BaseServer
> > > > +from SimpleHTTPServer import SimpleHTTPRequestHandler
> > > > +from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
> > > > +from OpenSSL import SSL
> > > >
> > > > -def filter_xml(name, type, ns, sysname):
> > > > +def filter_xml(name, type, ns, sysname, interopNS):
> > > > return """
> > > > <?xml version="1.0" encoding="utf-8"?>
> > > > <CIM CIMVERSION="2.0" DTDVERSION="2.0">
> > > > @@ -20,8 +27,8 @@
> > > > <SIMPLEREQ>
> > > > <IMETHODCALL NAME="CreateInstance">
> > > > <LOCALNAMESPACEPATH>
> > > > - <NAMESPACE NAME="root"/>
> > > > - <NAMESPACE NAME="PG_InterOp"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > </LOCALNAMESPACEPATH>
> > > > <IPARAMVALUE NAME="NewInstance">
> > > > <INSTANCE CLASSNAME="CIM_IndicationFilter">
> > > > @@ -53,9 +60,9 @@
> > > > </SIMPLEREQ>
> > > > </MESSAGE>
> > > > </CIM>
> > > > - """ % (sysname, name, type, ns)
> > > > + """ % (interopNS[0], interopNS[1], sysname, name, type, ns)
> > > >
> > > > -def handler_xml(name, port, sysname):
> > > > +def handler_xml(name, destUrl, sysname, interopNS):
> > > > return """
> > > > <?xml version="1.0" encoding="utf-8"?>
> > > > <CIM CIMVERSION="2.0" DTDVERSION="2.0">
> > > > @@ -63,8 +70,8 @@
> > > > <SIMPLEREQ>
> > > > <IMETHODCALL NAME="CreateInstance">
> > > > <LOCALNAMESPACEPATH>
> > > > - <NAMESPACE NAME="root"/>
> > > > - <NAMESPACE NAME="PG_InterOp"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > </LOCALNAMESPACEPATH>
> > > > <IPARAMVALUE NAME="NewInstance">
> > > > <INSTANCE CLASSNAME="CIM_IndicationHandlerCIMXML">
> > > > @@ -81,7 +88,7 @@
> > > > <VALUE>%sHandler</VALUE>
> > > > </PROPERTY>
> > > > <PROPERTY NAME="Destination" TYPE="string">
> > > > - <VALUE>http://localhost:%i</VALUE>
> > > > + <VALUE>%s</VALUE>
> > > > </PROPERTY>
> > > > </INSTANCE>
> > > > </IPARAMVALUE>
> > > > @@ -89,9 +96,9 @@
> > > > </SIMPLEREQ>
> > > > </MESSAGE>
> > > > </CIM>
> > > > - """ % (sysname, name, port)
> > > > + """ % (interopNS[0], interopNS[1], sysname, name, destUrl)
> > > >
> > > > -def subscription_xml(name, sysname):
> > > > +def subscription_xml(name, sysname, interopNS):
> > > > return """
> > > > <?xml version="1.0" encoding="utf-8"?>
> > > > <CIM CIMVERSION="2.0" DTDVERSION="2.0">
> > > > @@ -99,8 +106,8 @@
> > > > <SIMPLEREQ>
> > > > <IMETHODCALL NAME="CreateInstance">
> > > > <LOCALNAMESPACEPATH>
> > > > - <NAMESPACE NAME="root"/>
> > > > - <NAMESPACE NAME="PG_InterOp"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > </LOCALNAMESPACEPATH>
> > > > <IPARAMVALUE NAME="NewInstance">
> > > > <INSTANCE CLASSNAME="CIM_IndicationSubscription">
> > > > @@ -167,9 +174,9 @@
> > > > </SIMPLEREQ>
> > > > </MESSAGE>
> > > > </CIM>
> > > > - """ % (sysname, name, sysname, name)
> > > > + """ % (interopNS[0], interopNS[1], sysname, name, sysname,
> name)
> > > >
> > > > -def delete_inst_xml(name, type, sysname, inst_name):
> > > > +def delete_inst_xml(name, type, sysname, inst_name, interopNS):
> > > > return """
> > > > <?xml version="1.0" encoding="utf-8"?>
> > > > <CIM CIMVERSION="2.0" DTDVERSION="2.0">
> > > > @@ -177,8 +184,8 @@
> > > > <SIMPLEREQ>
> > > > <IMETHODCALL NAME="DeleteInstance">
> > > > <LOCALNAMESPACEPATH>
> > > > - <NAMESPACE NAME="root"/>
> > > > - <NAMESPACE NAME="PG_InterOp"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > </LOCALNAMESPACEPATH>
> > > > <IPARAMVALUE NAME="InstanceName">
> > > > <INSTANCENAME CLASSNAME="CIM_Indication%s">
> > > > @@ -200,9 +207,9 @@
> > > > </SIMPLEREQ>
> > > > </MESSAGE>
> > > > </CIM>;
> > > > - """ % (type, sysname, type, inst_name);
> > > > + """ % (interopNS[0], interopNS[1], type, sysname, type,
> inst_name);
> > > >
> > > > -def delete_sub_xml(name, sysname):
> > > > +def delete_sub_xml(name, sysname, interopNS):
> > > > return """
> > > > <?xml version="1.0" encoding="utf-8"?>
> > > > <CIM CIMVERSION="2.0" DTDVERSION="2.0">
> > > > @@ -210,8 +217,8 @@
> > > > <SIMPLEREQ>
> > > > <IMETHODCALL NAME="DeleteInstance">
> > > > <LOCALNAMESPACEPATH>
> > > > - <NAMESPACE NAME="root"/>
> > > > - <NAMESPACE NAME="PG_InterOp"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > </LOCALNAMESPACEPATH>
> > > > <IPARAMVALUE NAME="InstanceName">
> > > > <INSTANCENAME CLASSNAME="CIM_IndicationSubscription">
> > > > @@ -273,7 +280,45 @@
> > > > </SIMPLEREQ>
> > > > </MESSAGE>
> > > > </CIM>;
> > > > - """ % (sysname, name, sysname, name)
> > > > + """ % (interopNS[0], interopNS[1], sysname, name, sysname,
> name)
> > > > +
> > > > +def trigger_xml(type, interopNS):
> > > > + return """
> > > > + <?xml version="1.0" encoding="utf-8"?>
> > > > + <CIM CIMVERSION="2.0" DTDVERSION="2.0">
> > > > + <MESSAGE ID="4711" PROTOCOLVERSION="1.0">
> > > > + <SIMPLEREQ>
> > > > + <METHODCALL NAME="SendTestIndication">
> > > > + <LOCALCLASSPATH>
> > > > + <LOCALNAMESPACEPATH>
> > > > + <NAMESPACE NAME="%s"/>
> > > > + <NAMESPACE NAME="%s"/>
> > > > + </LOCALNAMESPACEPATH>
> > > > + <CLASSNAME NAME="%s"/>
> > > > + </LOCALCLASSPATH>
> > > > + </METHODCALL>
> > > > + </SIMPLEREQ>
> > > > + </MESSAGE>
> > > > + </CIM>
> > > > + """ % (interopNS[0], interopNS[1], type)
> > > > + # FIXME: this should really use indication NS, not interop NS.
> > > > +
> > > > +def update_url_port(parsedUrl, port):
> > > > + # Must manually reconstruct netloc to update the port value.
> > > > + if isinstance(parsedUrl.username, basestring):
> > > > + if isinstance(parsedUrl.password, basestring):
> > > > + netloc = "%s:%s@%s:%s" % (parsedUrl.username,
> > > parsedUrl.password,
> > > > + parsedUrl.hostname, port)
> > > > + else:
> > > > + netloc = "%s@%s:%s" % (parsedUrl.username,
> > > > + parsedUrl.hostname, port)
> > > > + else:
> > > > + netloc = "%s:%s" % (parsedUrl.hostname, port)
> > > > +
> > > > + # Reassemble url with the updated netloc. return a string.
> > > > + return urlunparse((parsedUrl.scheme, netloc,
> > > > + parsedUrl.path, parsedUrl.params,
> > > > + parsedUrl.query, parsedUrl.fragment))
> > > >
> > > > class CIMIndication:
> > > > def __init__(self, xmldata):
> > > > @@ -286,50 +331,135 @@
> > > > def __str__(self):
> > > > return self.name
> > > >
> > > > -class CIMSocketHandler(BaseHTTPServer.BaseHTTPRequestHandler):
> > > > +def socket_handler_wrapper(*parms):
> > > > + try:
> > > > + CIMSocketHandler(*parms)
> > > > + except Exception as e:
> > > > + print "SSL error: %s" % str(e)
> > > > +
> > > > +class CIMSocketHandler(SimpleHTTPRequestHandler):
> > > > + def setup(self):
> > > > + self.connection = self.request
> > > > + self.rfile = socket._fileobject(self.request, "rb",
> > > self.rbufsize)
> > > > + self.wfile = socket._fileobject(self.request, "wb",
> > > self.wbufsize)
> > > > +
> > > > def do_POST(self):
> > > > length = self.headers.getheader('content-length')
> > > > data = self.rfile.read(int(length))
> > > >
> > > > indication = CIMIndication(data)
> > > > - print "Got indication: %s" % indication
> > > > + print "Got indication: %s from %s" % (indication,
> > > > self.client_address)
> > > > if self.server.print_ind:
> > > > - print "%s\n\n" % data
> > > > + print "%s\n" % data
> > > > self.server.indications.append(indication)
> > > > + # Silence the unwanted log output from send_response()
> > > > + realStderr = sys.stderr
> > > > + sys.stderr = open(os.devnull,'a')
> > > > + self.send_response(200)
> > > > + sys.stderr = realStderr
> > > > +
> > > > +class SecureHTTPServer(HTTPServer):
> > > > + def __init__(self, server_address, HandlerClass):
> > > > + BaseServer.__init__(self, server_address, HandlerClass)
> > > > +
> > > > + def verify_cb(conn, cert, errnum, depth, ok):
> > > > + if options.verbose:
> > > > + print('Verify peer certificate chain: level %d:' %
> depth)
> > > > + print('subject=%s' % cert.get_subject())
> > > > + print('issuer =%s' % cert.get_issuer())
> > > > + return ok
> > > > +
> > > > + ctx = SSL.Context(SSL.SSLv23_METHOD)
> > > > + #ctx.use_certificate_file(options.certFile)
> > > > + ctx.use_certificate_chain_file(options.certFile)
> > > > + ctx.use_privatekey_file(options.keyFile)
> > > > +
> > > > + if options.noverify:
> > > > + ctx.set_verify(SSL.VERIFY_NONE, verify_cb)
> > > > + else:
> > > > + #ctx.set_verify(SSL.VERIFY_PEER, verify_cb)
> > > > +
> > > ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
> > > > + verify_cb)
> > > > + ctx.load_verify_locations(options.trustStore)
> > > > +
> > > > + self.socket = SSL.Connection(ctx,
> > > > socket.socket(self.address_family,
> > > > +
> > > self.socket_type))
> > > > + self.server_bind()
> > > > + self.server_activate()
> > > >
> > > > +# The param defaults allow new options from main() w/o losing
> compat w/
> > > > cimtest.
> > > > class CIMIndicationSubscription:
> > > > - def __init__(self, name, typ, ns, print_ind, sysname, port=0):
> > > > + def __init__(self, name, typ, ns, print_ind, sysname, port=0,
> > > > + interopNS=('root','PG_InterOp'),
> > > > destUrl="http://localhost:8000",
> > > > + triggermode=False):
> > > > self.name = name
> > > > self.type = typ
> > > > self.ns = ns
> > > > self.sysname = sysname
> > > > + self.interopNS = interopNS
> > > > + self.print_ind = print_ind
> > > > +
> > > > + # We do not want to open a listener socket in trigger mode.
> > > > + if triggermode:
> > > > + self.trigger_xml = trigger_xml(typ, interopNS)
> > > > + return
> > > > +
> > > > + parsedUrl = urlparse(destUrl)
> > > > +
> > > > + # Increment the listener port by the offset value.
> > > > + if isinstance(parsedUrl.port, int):
> > > > + listenerPort = parsedUrl.port + port
> > > > + else:
> > > > + listenerPort = 8000 + port
> > > > +
> > > > + destUrl = update_url_port(parsedUrl, listenerPort)
> > > > +
> > > > + try:
> > > > + if parsedUrl.scheme == "http":
> > > > + self.server = HTTPServer((parsedUrl.hostname,
> > > > + listenerPort),
> > > > + CIMSocketHandler)
> > > > + elif parsedUrl.scheme == "https":
> > > > + self.server = SecureHTTPServer((parsedUrl.hostname,
> > > > + listenerPort),
> > > > +
> socket_handler_wrapper)
> > > > + except IOError as e:
> > > > + print "Error creating listener socket: %s" % str(e)
> > > > + exit(e.errno)
> > > >
> > > > - 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)
> > > > + self.filter_xml = filter_xml(name, typ, ns, sysname,
> interopNS)
> > > > + self.handler_xml = handler_xml(name, destUrl, sysname,
> > > interopNS)
> > > > + self.subscription_xml = subscription_xml(name, sysname,
> > > interopNS)
> > > >
> > > > def __do_cimpost(self, conn, body, method, auth_hdr=None):
> > > > headers = {"CIMOperation" : "MethodCall",
> > > > "CIMMethod" : method,
> > > > - "CIMObject" : "root/PG_Interop",
> > > > + #"CIMObject" : "root/PG_Interop",
> > > > + "CIMObject" : "%s/%s" % self.interopNS,
> > > > "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()
> > > > + try:
> > > > + 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))
> > > > + except IOError as e:
> > > > + print "Error connecting to CIMOM: %s" % str(e)
> > > > + exit(e.errno)
> > > > +
> > > > + if self.print_ind:
> > > > + print "Reply from CIMOM:"
> > > > + #print resp.msg
> > > > + print resp.read()
> > > > + else:
> > > > + resp.read()
> > > >
> > > > def subscribe(self, url, cred=None):
> > > > self.conn = httplib.HTTPConnection(url)
> > > > @@ -353,26 +483,39 @@
> > > > else:
> > > > auth_hdr = None
> > > >
> > > > - xml = delete_sub_xml(self.name, self.sysname)
> > > > + xml = delete_sub_xml(self.name, self.sysname,
> self.interopNS)
> > > > self.__do_cimpost(self.conn, xml,
> > > > "DeleteInstance", auth_hdr)
> > > > xml = delete_inst_xml(self.name, "HandlerCIMXML",
> self.sysname,
> > > > - "%sHandler" % self.name)
> > > > + "%sHandler" % self.name,
> self.interopNS)
> > > > self.__do_cimpost(self.conn, xml,
> > > > "DeleteInstance", auth_hdr)
> > > > xml = delete_inst_xml(self.name, "Filter", self.sysname,
> > > > - "%sFilter" % self.name)
> > > > + "%sFilter" % self.name,
> self.interopNS)
> > > > self.__do_cimpost(self.conn, xml,
> > > > "DeleteInstance", auth_hdr)
> > > >
> > > > -def dump_xml(name, typ, ns, sysname):
> > > > - filter_str = filter_xml(name, typ, ns, sysname)
> > > > - handler_str = handler_xml(name, 8000, sysname)
> > > > - subscript_str = subscription_xml(name, sysname)
> > > > - del_filter_str = delete_inst_xml(name, "Filter", sysname,
> > > "%sFilter" %
> > > > name)
> > > > + def trigger(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.trigger_xml,
> > > > + "SendTestIndication", auth_hdr)
> > > > +
> > > > +def dump_xml(name, typ, ns, sysname, interopNS, destUrl):
> > > > + filter_str = filter_xml(name, typ, ns, sysname, interopNS)
> > > > + handler_str = handler_xml(name, destUrl, sysname, interopNS)
> > > > + subscript_str = subscription_xml(name, sysname, interopNS)
> > > > + del_filter_str = delete_inst_xml(name, "Filter", sysname,
> > > "%sFilter" %
> > > > name,
> > > > + interopNS)
> > > > del_handler_str = delete_inst_xml(name, "HandlerCIMXML",
> sysname,
> > > > - "%sHandler" % name)
> > > > - del_subscript_str = delete_sub_xml(name, sysname)
> > > > + "%sHandler" % name,
> interopNS)
> > > > + del_subscript_str = delete_sub_xml(name, sysname, interopNS)
> > > > + trigger_str = trigger_xml(typ, interopNS)
> > > >
> > > > print "CreateFilter:\n%s\n" % filter_str
> > > > print "DeleteFilter:\n%s\n" % del_filter_str
> > > > @@ -380,15 +523,20 @@
> > > > print "DeleteHandler:\n%s\n" % del_handler_str
> > > > print "CreateSubscription:\n%s\n" % subscript_str
> > > > print "DeleteSubscription:\n%s\n" % del_subscript_str
> > > > + print "Indication trigger:\n%s\n" % trigger_str
> > > >
> > > > def main():
> > > > usage = "usage: %prog [options] provider\nex: %prog
> > > > CIM_InstModification"
> > > > parser = OptionParser(usage)
> > > >
> > > > + # FIXME: SecureHTTPServer still relies on this, need a better
> way.
> > > > + global options
> > > > +
> > > > parser.add_option("-u", "--url", dest="url",
> > > default="localhost:5988",
> > > > help="URL of CIMOM to connect to
> (host:port)")
> > > > - parser.add_option("-N", "--ns", dest="ns", default="root/virt",
> > > > - help="Namespace (default is root/virt)")
> > > > + parser.add_option("-N", "--ns", dest="ns",
> > > > + help="Namespace in which the register the
> > > indication
> > > > \
> > > > + (default is the same value as the interop
> > > > namespace)")
> > > > parser.add_option("-n", "--name", dest="name", default="Test",
> > > > help="Name for filter, handler, subscription
> \
> > > > (default: Test)")
> > > > @@ -398,16 +546,41 @@
> > > > parser.add_option("-p", "--print-ind", dest="print_ind",
> > > default=False,
> > > > action="store_true",
> > > > help="Print received indications to stdout.")
> > > > + parser.add_option("-v", "--verbose", dest="verbose",
> default=False,
> > > > + action="store_true",
> > > > + help="Print addtional debug info.")
> > > > parser.add_option("-U", "--user", dest="username",
> default=None,
> > > > - help="HTTP Auth username")
> > > > + help="HTTP Auth username (CIMOM)")
> > > > parser.add_option("-P", "--pass", dest="password",
> default=None,
> > > > - help="HTTP Auth password")
> > > > + help="HTTP Auth password (CIMOM)")
> > > > parser.add_option("--port", dest="port", default=0, type=int,
> > > > help="Port increment value (server default:
> > > 8000)")
> > > > + parser.add_option("--dest", dest="destUrl",
> > > default="localhost:8000",
> > > > + help="URL of destination handler \
> > > > + (default: http://localhost:8000)")
> > > > + parser.add_option("--certFile", dest="certFile", default=None,
> > > > + help="File containing the local certificate
> to
> > > use")
> > > > + parser.add_option("--keyFile", dest="keyFile", default=None,
> > > > + help="File containing private key for local
> cert
> > > \
> > > > + (if none provided, assume key is in the
> > > certFile)")
> > > > + parser.add_option("--trustStore", dest="trustStore",
> default=None,
> > > > + help="File containing trusted certificates
> for \
> > > > + remote endpoint verification")
> > > > + parser.add_option("--noverify", dest="noverify", default=False,
> > > > + action="store_true",
> > > > + help="Skip verification of remote endpoint
> > > > certificate \
> > > > + for incoming https indications")
> > > > + parser.add_option("-i", "--interop", dest="interop",
> > > > + default="root/interop",
> > > > + help="Interop namespace name (default:
> > > > root/interop)")
> > > > + parser.add_option("-t", "--trigger", dest="trigger",
> default=False,
> > > > + action="store_true",
> > > > + help="Trigger mode: send a request to CIMOM
> to
> > > > trigger \
> > > > + an indication via a method call ")
> > > >
> > > > (options, args) = parser.parse_args()
> > > >
> > > > - if len(args) == 0:
> > > > + if not options.trigger and len(args)==0:
> > > > print "Fatal: no indication type provided."
> > > > sys.exit(1)
> > > >
> > > > @@ -421,20 +594,75 @@
> > > > else:
> > > > sysname = options.url
> > > >
> > > > + if "/" in options.interop:
> > > > + options.interopNS = tuple(options.interop.split("/"))
> > > > + else:
> > > > + options.interopNS = ("root", options.interop)
> > > > +
> > > > + # If no value provided for indication NS, default is same as
> > > interopNS.
> > > > + if not options.ns:
> > > > + options.ns = "%s/%s" % options.interopNS
> > > > +
> > > > + if options.verbose:
> > > > + print "Interop namespace = %s/%s" % options.interopNS
> > > > + print "Indication namespace = %s" % options.ns
> > > > +
> > > > + # If url does not begin with http or https, assume http.
> > > > + parsedUrl = urlparse(options.destUrl)
> > > > + if not re.search(parsedUrl.scheme, "https"):
> > > > + destUrl = "http://" + options.destUrl
> > > > + else:
> > > > + destUrl = options.destUrl
> > > > +
> > > > + if parsedUrl.scheme == "https":
> > > > + if not options.trustStore and not options.noverify:
> > > > + print "Error: must provide --trustStore or --noverify
> with
> > > > https."
> > > > + sys.exit(1)
> > > > + elif options.trustStore and options.noverify:
> > > > + print "Error: options --trustStore and --noverify are
> > > > exclusive."
> > > > + sys.exit(1)
> > > > + if not options.certFile:
> > > > + print "Error: no certificate file provided."
> > > > + sys.exit(1)
> > > > + elif not options.keyFile:
> > > > + print "No keyFile provided; assuming private key \
> > > > + contained in certFile."
> > > > + options.keyFile = options.certFile
> > > > +
> > > > if options.dump:
> > > > - dump_xml(options.name, args[0], options.ns, sysname)
> > > > + if isinstance(parsedUrl.port, int):
> > > > + listenerPort = parsedUrl.port + options.port
> > > > + else:
> > > > + listenerPort = 8000 + options.port
> > > > +
> > > > + destUrl = update_url_port(parsedUrl, listenerPort)
> > > > + dump_xml(options.name, args[0], options.ns, sysname,
> > > > options.interopNS,
> > > > + destUrl)
> > > > + sys.exit(0)
> > > > +
> > > > + # Trigger mode: currently only supports SFCB Test_Indication
> > > provider.
> > > > + if options.trigger:
> > > > + classname = "Test_Indication"
> > > > + sub = CIMIndicationSubscription(options.name, classname,
> > > > options.ns,
> > > > + options.print_ind, sysname,
> > > > options.port,
> > > > + options.interopNS, destUrl,
> True)
> > > > + print "Triggering indication for %s" % classname
> > > > + sub.trigger(options.url, auth)
> > > > sys.exit(0)
> > > >
> > > > sub = CIMIndicationSubscription(options.name, args[0],
> options.ns,
> > > > - options.print_ind, sysname,
> > > > options.port)
> > > > + options.print_ind, sysname,
> > > > options.port,
> > > > + options.interopNS, destUrl)
> > > > +
> > > > + print "Creating subscription for %s" % args[0]
> > > > sub.subscribe(options.url, auth)
> > > > print "Watching for %s" % args[0]
> > > >
> > > > try:
> > > > sub.server.serve_forever()
> > > > - except KeyboardInterrupt,e:
> > > > - sub.unsubscribe(auth)
> > > > + except KeyboardInterrupt as e:
> > > > print "Cancelling subscription for %s" % args[0]
> > > > + sub.unsubscribe(auth)
> > > >
> > > > if __name__=="__main__":
> > > > sys.exit(main())
> > > >
> > > > _______________________________________________
> > > > Libvirt-cim mailing list
> > > > Libvirt-cim at redhat.com
> > > > https://www.redhat.com/mailman/listinfo/libvirt-cim
> > > >
> > >
> > >
> > > _______________________________________________
> > > Libvirt-cim mailing list
> > > Libvirt-cim at redhat.com
> > > https://www.redhat.com/mailman/listinfo/libvirt-cim
> >
> > _______________________________________________
> > Libvirt-cim mailing list
> > Libvirt-cim at redhat.com
> > https://www.redhat.com/mailman/listinfo/libvirt-cim
> >
>
>
> _______________________________________________
> Libvirt-cim mailing list
> Libvirt-cim at redhat.com
> https://www.redhat.com/mailman/listinfo/libvirt-cim
More information about the Libvirt-cim
mailing list