source: fedd/fedd_client.py @ f8b118e

axis_examplecompt_changesinfo-opsversion-1.30version-2.00version-3.01version-3.02
Last change on this file since f8b118e was f8b118e, checked in by Ted Faber <faber@…>, 16 years ago

clean up service classes a bit

  • Property mode set to 100755
File size: 22.1 KB
Line 
1#!/usr/local/bin/python
2
3import sys
4import os
5import pwd
6
7from fedd_services import *
8from fedd_internal_services import *
9
10from M2Crypto import SSL, X509
11from M2Crypto.m2xmlrpclib import SSL_Transport
12import M2Crypto.httpslib
13
14from xmlrpclib import ServerProxy, Error, dumps, loads
15from ZSI import SoapWriter
16from ZSI.TC import QName, String, URI, AnyElement, UNBOUNDED, Any
17from ZSI.wstools.Namespaces import SOAP
18from ZSI.fault import FaultType, Detail
19
20import xmlrpclib
21
22from fedd_util import fedid, fedd_ssl_context, pack_id, unpack_id, \
23        service_caller
24from service_error import *
25
26from optparse import OptionParser, OptionValueError
27
28import parse_detail
29
30# Turn off the matching of hostname to certificate ID
31SSL.Connection.clientPostConnectionCheck = None
32
33class IDFormatException(RuntimeError): pass
34
35class access_method:
36    """Encapsulates an access method generically."""
37    (type_ssh, type_x509, type_pgp) = ('sshPubkey', 'X509', 'pgpPubkey')
38    default_type = type_ssh
39    def __init__(self, buf=None, type=None, file=None):
40        self.buf = buf
41
42        if type != None: self.type = type
43        else: self.type = access_method.default_type
44
45        if file != None:
46            self.readfile(file)
47   
48    def readfile(self, file, type=None):
49        f = open(file, "r")
50        self.buf = f.read();
51        f.close()
52        if type == None:
53            if self.type == None:
54                self.type = access_method.default_type
55        else:
56            self.type = type;
57   
58class node_desc:
59    def __init__(self, image, hardware, count=1):
60        if getattr(image, "__iter__", None) == None:
61            if image == None: self.image = [ ]
62            else: self.image = [ image ]
63        else:
64            self.image = image
65
66        if getattr(hardware, "__iter__", None) == None: 
67            if hardware == None: self.hardware = [ ]
68            else: self.hardware = [ hardware ]
69        else:
70            self.hardware = hardware
71        if count != None: self.count = int(count)
72        else: self.count = 1
73
74class fedd_client_opts(OptionParser):
75    """Encapsulate option processing in this class, rather than in main"""
76    def __init__(self):
77        OptionParser.__init__(self, usage="%prog [opts] (--help for details)",
78                version="0.1")
79
80        self.add_option("-c","--cert", action="store", dest="cert",
81                type="string", help="my certificate file")
82        self.add_option("-d", "--debug", action="count", dest="debug", 
83                default=0, help="Set debug.  Repeat for more information")
84        self.add_option("-s", "--serializeOnly", action="store_true", 
85                dest="serialize_only", default=False,
86                help="Print the SOAP request that would be sent and exit")
87        self.add_option("-T","--trusted", action="store", dest="trusted",
88                type="string", help="Trusted certificates (required)")
89        self.add_option("-u", "--url", action="store", dest="url",
90                type="string",default="https://localhost:23235", 
91                help="URL to connect to (default %default)")
92        self.add_option("-x","--transport", action="store", type="choice",
93                choices=("xmlrpc", "soap"), default="soap",
94                help="Transport for request (xmlrpc|soap) (Default: %default)")
95        self.add_option("--trace", action="store_const", dest="tracefile", 
96                const=sys.stderr, help="Print SOAP exchange to stderr")
97
98class fedd_create_opts(fedd_client_opts):
99    def __init__(self, access_keys, add_key_callback=None, 
100            add_cert_callback=None):
101        fedd_client_opts.__init__(self)
102        self.add_option("-e", "--experiment_cert", dest="out_certfile",
103                type="string", help="output certificate file")
104        self.add_option("-E", "--experiment_name", dest="exp_name",
105                type="string", help="output certificate file")
106        self.add_option("-F","--useFedid", action="store_true",
107                dest="use_fedid", default=False,
108                help="Use a fedid derived from my certificate as user identity")
109        self.add_option("-f", "--file", dest="file", 
110                help="experiment description file")
111        if add_key_callback:
112            self.add_option("-k", "--sshKey", action="callback", type="string", 
113                    callback=add_key_callback, callback_args=(access_keys,),
114                    help="ssh key for access (can be supplied more than once")
115        if add_cert_callback:
116            self.add_option("-K", "--x509Key", action="callback",
117                    type="string", callback=add_cert_callback,
118                    callback_args=(access_keys,),
119                    help="X509 certificate for access " + \
120                        "(can be supplied more than once")
121        self.add_option("-m", "--master", dest="master",
122                help="Master testbed in the federation")
123        self.add_option("-U", "--username", action="store", dest="user",
124                type="string", help="Use this username instead of the uid")
125
126class fedd_split_opts(fedd_create_opts):
127    def __init__(self, access_keys, add_key_callback=None, 
128            add_cert_callback=None):
129        fedd_create_opts.__init__(self, access_keys, add_key_callback,
130                add_cert_callback)
131        self.add_option('-t','--fedkit', action='store_true', dest='fedkit',
132                default=False,
133                help="get output suitable for federation kit install")
134
135
136class fedd_access_opts(fedd_create_opts):
137    def __init__(self, access_keys, node_descs, add_key_callback=None, 
138            add_cert_callback=None, add_node_callback=None):
139        fedd_create_opts.__init__(self, access_keys, add_key_callback,
140                add_cert_callback)
141        self.add_option("-a","--anonymous", action="store_true",
142                dest="anonymous", default=False,
143                help="Do not include a user in the request")
144        self.add_option("-l","--label", action="store", dest="label",
145                type="string", help="Label for output")
146        if add_node_callback:
147            self.add_option("-n", "--node", action="callback", type="string", 
148                    callback=add_node_callback, callback_args=(node_descs,),
149                    help="Node description: image:hardware[:count]")
150        self.add_option("-p", "--project", action="store", dest="project", 
151                type="string",
152                help="Use a project request with this project name")
153        self.add_option("-t", "--testbed", action="store", dest="testbed",
154                type="string",
155                help="Testbed identifier (URI) to contact (required)")
156
157class fedd_exp_data_opts(fedd_client_opts):
158    def __init__(self):
159        fedd_client_opts.__init__(self)
160        self.add_option("-e", "--experiment_cert", dest="exp_certfile",
161                type="string", help="output certificate file")
162        self.add_option("-E", "--experiment_name", dest="exp_name",
163                type="string", help="output certificate file")
164
165def exit_with_fault(dict, out=sys.stderr):
166    """ Print an error message and exit.
167
168    The dictionary contains the FeddFaultBody elements."""
169    codestr = ""
170
171    if dict.has_key('errstr'):
172        codestr = "Error: %s" % dict['errstr']
173
174    if dict.has_key('code'):
175        if len(codestr) > 0 : 
176            codestr += " (%d)" % dict['code']
177        else:
178            codestr = "Error Code: %d" % dict['code']
179
180    print>>out, codestr
181    print>>out, "Description: %s" % dict['desc']
182    sys.exit(dict.get('code', 20))
183# Base class that will do a the SOAP/XMLRPC exchange for a request.
184class fedd_rpc:
185    class RPCException:
186        def __init__(self, fb):
187            self.desc = fb.get('desc', None)
188            self.code = fb.get('code', -1)
189            self.errstr = fb.get('errstr', None)
190
191    def __init__(self, pre): 
192        """
193        Specialize the class for the pre method
194        """
195        self.RequestMessage = globals()["%sRequestMessage" % pre]
196        self.ResponseMessage = globals()["%sResponseMessage" % pre]
197        self.RequestBody="%sRequestBody" % pre
198        self.ResponseBody="%sResponseBody" % pre
199        self.method = pre
200
201        method_call = getattr(feddServiceLocator().getfeddPortType(),
202                self.method, None)
203        if method_call:
204            # The pre method is a fedd external service
205            self.caller = service_caller(self.method, 'getfeddPortType', 
206                    feddServiceLocator, self.RequestMessage, self.RequestBody)
207        else:
208            # The pre method is a fedd internal service
209            self.caller = service_caller(self.method, 
210                    'getfeddInternalPortType', feddInternalServiceLocator,
211                    self.RequestMessage, self.RequestBody)
212
213        self.RPCException = fedd_rpc.RPCException
214
215
216    def add_ssh_key(self, option, opt_str, value, parser, access_keys):
217        try:
218            access_keys.append(access_method(file=value,
219                type=access_method.type_ssh))
220        except IOError, (errno, strerror):
221            raise OptionValueError("Cannot generate sshPubkey from %s: "\
222                    "%s (%d)" % (value,strerror,errno))
223
224    def add_x509_cert(self, option, opt_str, value, parser, access_keys):
225        try:
226            access_keys.append(access_method(file=value,
227                type=access_method.type_x509))
228        except IOError, (errno, strerror):
229            raise OptionValueError("Cannot read x509 cert from %s: %s (%d)" %
230                    (value,strerror,errno))
231    def add_node_desc(self, option, opt_str, value, parser, node_descs):
232        def none_if_zero(x):
233            if len(x) > 0: return x
234            else: return None
235
236        params = map(none_if_zero, value.split(":"));
237       
238        if len(params) < 4 and len(params) > 1:
239            node_descs.append(node_desc(*params))
240        else:
241            raise OptionValueError("Bad node description: %s" % value)
242
243    def get_user_info(self, access_keys):
244        pw = pwd.getpwuid(os.getuid());
245        try_cert=None
246        user = None
247
248        if pw != None:
249            user = pw[0]
250            try_cert = "%s/.ssl/emulab.pem" % pw[5];
251            if not os.access(try_cert, os.R_OK):
252                try_cert = None
253            if len(access_keys) == 0:
254                for k in ["%s/.ssh/id_rsa.pub", "%s/.ssh/id_dsa.pub", 
255                        "%s/.ssh/identity.pub"]:
256                    try_key = k % pw[5];
257                    if os.access(try_key, os.R_OK):
258                        access_keys.append(access_method(file=try_key,
259                            type=access_method.type_ssh))
260                        break
261        return (user, try_cert)
262
263    def do_rpc(self, req_dict, url, transport, cert, trusted, tracefile=None,
264            serialize_only=False):
265        """
266        The work of sending and parsing the RPC as either XMLRPC or SOAP
267        """
268
269        context = None
270        while context == None:
271            try:
272                context = fedd_ssl_context(cert, trusted)
273            except SSL.SSLError, e:
274                # Yes, doing this on message type is not ideal.  The string
275                # comes from OpenSSL, so check there is this stops working.
276                if str(e) == "bad decrypt": 
277                    print >>sys.stderr, "Bad Passphrase given."
278                else: raise
279
280        if transport == "soap":
281            if serialize_only:
282                sw = SoapWriter()
283                sw.serialize(req)
284                print str(sw)
285                sys.exit(0)
286            else:
287                try:
288                    resp = self.caller.call_soap_service(url, req_dict, 
289                            context=context, tracefile=tracefile)
290                except service_error, e:
291                    raise self.RPCException( {\
292                            'code': e.code, 
293                            'desc': e.desc, 
294                            'errstr': e.code_string()\
295                        })
296        elif transport == "xmlrpc":
297            if serialize_only:
298                ser = dumps((req_dict,))
299                print ser
300                sys.exit(0)
301            else:
302                try:
303                    resp = self.caller.call_xmlrpc_service(url, req_dict, 
304                            context=context, tracefile=tracefile)
305                except service_error, e:
306                    raise self.RPCException( {\
307                            'code': e.code, 
308                            'desc': e.desc, 
309                            'errstr': e.code_string()\
310                        })
311
312        else:
313            raise RuntimeError("Unknown RPC transport: %s" % transport)
314
315        if resp.has_key(self.ResponseBody):
316            return resp[self.ResponseBody]
317        else:
318            raise RuntimeError("No body in response??")
319
320# Querying experiment data follows the same control flow regardless of the
321# specific data retrieved.  This class encapsulates that control flow.
322class exp_data(fedd_rpc):
323    def __init__(self, op): 
324        """
325        Specialize the class for the type of data requested (op)
326        """
327
328        fedd_rpc.__init__(self, op)
329        if op =='Vtopo':
330            self.key="vtopo"
331            self.xml='experiment'
332        elif op == 'Vis':
333            self.key="vis"
334            self.xml='vis'
335        elif op == 'Info': pass
336        else:
337            raise TypeError("Bad op: %s" % op)
338
339    def print_xml(self, d, out=sys.stdout):
340        """
341        Print the retrieved data is a simple xml representation of the dict.
342        """
343        str = "<%s>\n" % self.xml
344        for t in ('node', 'lan'):
345            if d.has_key(t): 
346                for x in d[t]:
347                    str += "<%s>" % t
348                    for k in x.keys():
349                        str += "<%s>%s</%s>" % (k, x[k],k)
350                    str += "</%s>\n" % t
351        str+= "</%s>" % self.xml
352        print >>out, str
353
354    def __call__(self):
355        """
356        The control flow.  Compose the request and print the response.
357        """
358        # Process the options using the customized option parser defined above
359        parser = fedd_exp_data_opts()
360
361        (opts, args) = parser.parse_args()
362
363        if opts.trusted != None:
364            if ( not os.access(opts.trusted, os.R_OK) ) :
365                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
366        else:
367            parser.error("--trusted is required")
368
369        if opts.debug > 0: opts.tracefile=sys.stderr
370
371        if opts.cert != None: cert = opts.cert
372
373        if cert == None:
374            sys.exit("No certificate given (--cert) or found")
375
376        if os.access(cert, os.R_OK):
377            fid = fedid(file=cert)
378        else:
379            sys.exit("Cannot read certificate (%s)" % cert)
380
381        if opts.exp_name and opts.exp_certfile:
382            sys.exit("Only one of --experiment_cert and " +\
383                    "--experiment_name permitted");
384
385        if opts.exp_certfile:
386            exp_id = { 'fedid': fedid(file=opts.exp_certfile) }
387
388        if opts.exp_name:
389            exp_id = { 'localname' : opts.exp_name }
390
391        req = { 'experiment': exp_id }
392
393        try:
394            resp_dict = self.do_rpc(req,
395                    opts.url, opts.transport, cert, opts.trusted, 
396                    serialize_only=opts.serialize_only,
397                    tracefile=opts.tracefile)
398        except self.RPCException, e:
399            exit_with_fault(\
400                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
401        except RuntimeError, e:
402            print e
403            sys.exit("Error processing RPC: %s" % e)
404
405        if getattr(self, 'key', None):
406            try:
407                if resp_dict.has_key(self.key):
408                    self.print_xml(resp_dict[self.key])
409            except RuntimeError, e:
410                sys.exit("Bad response. %s" % e.message)
411        else:
412            print resp_dict
413
414class terminate(fedd_rpc):
415    def __init__(self): 
416        """
417        Termination request
418        """
419
420        fedd_rpc.__init__(self, "Terminate")
421
422    def __call__(self):
423        """
424        The control flow.  Compose the request and print the response.
425        """
426        # Process the options using the customized option parser defined above
427        parser = fedd_exp_data_opts()
428
429        (opts, args) = parser.parse_args()
430
431        if opts.trusted != None:
432            if ( not os.access(opts.trusted, os.R_OK) ) :
433                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
434        else:
435            parser.error("--trusted is required")
436
437        if opts.debug > 0: opts.tracefile=sys.stderr
438
439        if opts.cert != None: cert = opts.cert
440
441        if cert == None:
442            sys.exit("No certificate given (--cert) or found")
443
444        if os.access(cert, os.R_OK):
445            fid = fedid(file=cert)
446        else:
447            sys.exit("Cannot read certificate (%s)" % cert)
448
449        if opts.exp_name and opts.exp_certfile:
450            sys.exit("Only one of --experiment_cert and " +\
451                    "--experiment_name permitted");
452
453        if opts.exp_certfile:
454            exp_id = { 'fedid': fedid(file=opts.exp_certfile) }
455
456        if opts.exp_name:
457            exp_id = { 'localname' : opts.exp_name }
458
459        req = { 'experiment': exp_id }
460
461        try:
462            resp_dict = self.do_rpc(req,
463                    opts.url, opts.transport, cert, opts.trusted, 
464                    serialize_only=opts.serialize_only,
465                    tracefile=opts.tracefile)
466        except self.RPCException, e:
467            exit_with_fault(\
468                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
469        except RuntimeError, e:
470            print e
471            sys.exit("Error processing RPC: %s" % e)
472
473        eid = resp_dict.get('experimentID', None)
474        if eid:
475            for id in eid:
476                for k in id.keys():
477                    if k == 'fedid': print "%s: %s" % (k,fedid(bits=id[k]))
478                    else: print "%s: %s" % (k, id[k])
479
480class create(fedd_rpc):
481    def __init__(self): 
482        fedd_rpc.__init__(self, "Create")
483    def __call__(self):
484        access_keys = []
485        # Process the options using the customized option parser defined above
486        parser = fedd_create_opts(access_keys, self.add_ssh_key,
487                self.add_x509_cert)
488
489        (opts, args) = parser.parse_args()
490
491        if opts.trusted != None:
492            if ( not os.access(opts.trusted, os.R_OK) ) :
493                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
494        else:
495            parser.error("--trusted is required")
496
497        if opts.debug > 0: opts.tracefile=sys.stderr
498
499        (user, cert) = self.get_user_info(access_keys)
500
501        if opts.user: user = opts.user
502
503        if opts.cert != None: cert = opts.cert
504
505        if cert == None:
506            sys.exit("No certificate given (--cert) or found")
507
508        if os.access(cert, os.R_OK):
509            fid = fedid(file=cert)
510            if opts.use_fedid == True:
511                user = fid
512        else:
513            sys.exit("Cannot read certificate (%s)" % cert)
514
515        if opts.file:
516            exp_desc = ""
517            try:
518                f = open(opts.file, 'r')
519                for line in f:
520                    exp_desc += line
521                f.close()
522            except IOError:
523                sys.exit("Cannot read description file (%s)" %opts.file)
524        else:
525            sys.exit("Must specify an experiment description (--file)")
526
527        if not opts.master:
528            sys.exit("Must specify a master testbed (--master)")
529
530        out_certfile = opts.out_certfile
531
532        msg = {
533                'experimentdescription': { 'ns2description': exp_desc },
534                'master': opts.master,
535                'user' : [ {\
536                        'userID': pack_id(user), \
537                        'access': [ { a.type: a.buf } for a in access_keys]\
538                        } ]
539                }
540
541        if opts.exp_name:
542            msg['experimentID'] = { 'localname': opts.exp_name }
543
544        if opts.debug > 1: print >>sys.stderr, msg
545
546        try:
547            resp_dict = self.do_rpc(msg, 
548                    opts.url, opts.transport, cert, opts.trusted, 
549                    serialize_only=opts.serialize_only,
550                    tracefile=opts.tracefile)
551        except self.RPCException, e:
552            exit_with_fault(\
553                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
554        except RuntimeError, e:
555            sys.exit("Error processing RPC: %s" % e)
556
557        if opts.debug > 1: print >>sys.stderr, resp_dict
558
559        ea = resp_dict.get('experimentAccess', None)
560        if out_certfile and ea and ea.has_key('X509'):
561            try:
562                f = open(out_certfile, "w")
563                print >>f, ea['X509']
564                f.close()
565            except IOError:
566                sys.exit('Could not write to %s' %  out_certfile)
567        eid = resp_dict.get('experimentID', None)
568        if eid:
569            for id in eid:
570                for k in id.keys():
571                    print "%s: %s" % (k, id[k])
572
573class split(fedd_rpc):
574    def __init__(self): 
575        fedd_rpc.__init__(self, "Ns2Split")
576    def __call__(self):
577        access_keys = []
578        # Process the options using the customized option parser defined above
579        parser = fedd_split_opts(access_keys, self.add_ssh_key,
580                self.add_x509_cert)
581
582        (opts, args) = parser.parse_args()
583
584        if opts.trusted != None:
585            if ( not os.access(opts.trusted, os.R_OK) ) :
586                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
587        else:
588            parser.error("--trusted is required")
589
590        if opts.debug > 0: opts.tracefile=sys.stderr
591
592        if opts.cert != None: cert = opts.cert
593        else: cert = None
594
595        if cert == None:
596            sys.exit("No certificate given (--cert) or found")
597
598        if os.access(cert, os.R_OK):
599            fid = fedid(file=cert)
600            if opts.use_fedid == True:
601                user = fid
602        else:
603            sys.exit("Cannot read certificate (%s)" % cert)
604
605        if opts.file:
606            exp_desc = ""
607            try:
608                f = open(opts.file, 'r')
609                for line in f:
610                    exp_desc += line
611                f.close()
612            except IOError:
613                sys.exit("Cannot read description file (%s)" %opts.file)
614        else:
615            sys.exit("Must specify an experiment description (--file)")
616
617        if not opts.master:
618            sys.exit("Must specify a master testbed (--master)")
619
620        out_certfile = opts.out_certfile
621
622        msg = {
623                'description': { 'ns2description': exp_desc },
624                'master': opts.master,
625                'include_fedkit': opts.fedkit,
626                }
627
628        if opts.debug > 1: print >>sys.stderr, msg
629
630        try:
631            resp_dict = self.do_rpc(msg, 
632                    opts.url, opts.transport, cert, opts.trusted, 
633                    serialize_only=opts.serialize_only,
634                    tracefile=opts.tracefile)
635        except self.RPCException, e:
636            exit_with_fault(\
637                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
638        except RuntimeError, e:
639            sys.exit("Error processing RPC: %s" % e)
640
641        if opts.debug > 1: print >>sys.stderr, resp_dict
642
643        out = resp_dict.get('output', None)
644
645        for line in out.splitlines():
646            print "%s" % line
647
648class access(fedd_rpc):
649    def __init__(self):
650        fedd_rpc.__init__(self, "RequestAccess")
651
652    def print_response_as_testbed(self, resp, label, out=sys.stdout):
653        """Print the response as input to the splitter script"""
654
655        e = resp['emulab']
656        p = e['project']
657        fields = { 
658                "Boss": e['boss'],
659                "OpsNode": e['ops'],
660                "Domain": e['domain'],
661                "FileServer": e['fileServer'],
662                "EventServer": e['eventServer'],
663                "Project": unpack_id(p['name'])
664                }
665        if (label != None): print >> out, "[%s]" % label
666
667        for l, v in fields.iteritems():
668            print >>out, "%s: %s" % (l, v)
669
670        for u in p['user']:
671            print >>out, "User: %s" % unpack_id(u['userID'])
672
673        for a in e['fedAttr']:
674            print >>out, "%s: %s" % (a['attribute'], a['value'])
675
676    def __call__(self):
677        access_keys = []
678        node_descs = []
679        proj = None
680
681        # Process the options using the customized option parser defined above
682        parser = fedd_access_opts(access_keys, node_descs, self.add_ssh_key,
683                self.add_x509_cert, self.add_node_desc)
684
685        (opts, args) = parser.parse_args()
686
687        if opts.testbed == None:
688            parser.error("--testbed is required")
689
690        if opts.trusted != None:
691            if ( not os.access(opts.trusted, os.R_OK) ) :
692                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
693        else:
694            parser.error("--trusted is required")
695
696        if opts.debug > 0: opts.tracefile=sys.stderr
697
698        (user, cert) = self.get_user_info(access_keys)
699
700        if opts.user: user = opts.user
701
702        if opts.cert != None: cert = opts.cert
703
704        if cert == None:
705            sys.exit("No certificate given (--cert) or found")
706
707        if os.access(cert, os.R_OK):
708            fid = fedid(file=cert)
709            if opts.use_fedid == True:
710                user = fid
711        else:
712            sys.exit("Cannot read certificate (%s)" % cert)
713
714        msg = {
715                'allocID': pack_id('test alloc'),
716                'destinationTestbed': pack_id(opts.testbed),
717                'serviceAccess' : [ { a.type: a.buf } for a in access_keys ],
718                'createAccess' : [ { a.type: a.buf } for a in access_keys ],
719                }
720
721        if len(node_descs) > 0:
722            msg['resources'] = { 
723                    'node': [ 
724                        { 
725                            'image':  n.image ,
726                            'hardware':  n.hardware,
727                            'count': n.count,
728                        } for n in node_descs],
729                    }
730
731        if opts.project != None:
732            if not opts.anonymous and user != None:
733                msg['project'] = {
734                        'name': pack_id(opts.project),
735                        'user': [ { 'userID': pack_id(user) } ],
736                        }
737            else:
738                msg['project'] = { 'name': pack_id(opts.project) }
739        else:
740            if not opts.anonymous and user != None:
741                msg['user'] = [ { 'userID': pack_id(user) } ]
742            else:
743                msg['user'] = [];
744
745        if opts.debug > 1: print >>sys.stderr, msg
746
747        try:
748            resp_dict = self.do_rpc(msg, 
749                    opts.url, opts.transport, cert, opts.trusted, 
750                    serialize_only=opts.serialize_only,
751                    tracefile=opts.tracefile)
752        except self.RPCException, e:
753            exit_with_fault(\
754                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
755        except RuntimeError, e:
756            sys.exit("Error processing RPC: %s" % e.message)
757
758        if opts.debug > 1: print >>sys.stderr, resp_dict
759        self.print_response_as_testbed(resp_dict, opts.label)
760
761cmds = {\
762        'create': create(),\
763        'split': split(),\
764        'access': access(),\
765        'vtopo': exp_data('Vtopo'),\
766        'vis': exp_data('Vis'),\
767        'info': exp_data('Info'),\
768        'terminate': terminate(),\
769    }
770
771operation = cmds.get(sys.argv[1], None)
772if operation:
773    del sys.argv[1]
774    operation()
775else:
776    sys.exit("Bad command: %s.  Valid ones are: %s" % \
777            (sys.argv[1], ", ".join(cmds.keys())))
778
Note: See TracBrowser for help on using the repository browser.