source: fedd/fedd_client.py @ a94cb0a

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

restore serialize

  • 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.TC import QName, String, URI, AnyElement, UNBOUNDED, Any
16from ZSI.wstools.Namespaces import SOAP
17from ZSI.fault import FaultType, Detail
18
19import xmlrpclib
20
21from fedd_util import fedd_ssl_context, pack_id, unpack_id
22from fedid import fedid
23from remote_service import 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                print self.caller.serialize_soap(req_dict) 
283                sys.exit(0)
284            else:
285                try:
286                    resp = self.caller.call_soap_service(url, req_dict, 
287                            context=context, tracefile=tracefile)
288                except service_error, e:
289                    raise self.RPCException( {\
290                            'code': e.code, 
291                            'desc': e.desc, 
292                            'errstr': e.code_string()\
293                        })
294        elif transport == "xmlrpc":
295            if serialize_only:
296                ser = dumps((req_dict,))
297                print ser
298                sys.exit(0)
299            else:
300                try:
301                    resp = self.caller.call_xmlrpc_service(url, req_dict, 
302                            context=context, tracefile=tracefile)
303                except service_error, e:
304                    raise self.RPCException( {\
305                            'code': e.code, 
306                            'desc': e.desc, 
307                            'errstr': e.code_string()\
308                        })
309
310        else:
311            raise RuntimeError("Unknown RPC transport: %s" % transport)
312
313        if resp.has_key(self.ResponseBody):
314            return resp[self.ResponseBody]
315        else:
316            raise RuntimeError("No body in response??")
317
318# Querying experiment data follows the same control flow regardless of the
319# specific data retrieved.  This class encapsulates that control flow.
320class exp_data(fedd_rpc):
321    def __init__(self, op): 
322        """
323        Specialize the class for the type of data requested (op)
324        """
325
326        fedd_rpc.__init__(self, op)
327        if op =='Vtopo':
328            self.key="vtopo"
329            self.xml='experiment'
330        elif op == 'Vis':
331            self.key="vis"
332            self.xml='vis'
333        elif op == 'Info': pass
334        else:
335            raise TypeError("Bad op: %s" % op)
336
337    def print_xml(self, d, out=sys.stdout):
338        """
339        Print the retrieved data is a simple xml representation of the dict.
340        """
341        str = "<%s>\n" % self.xml
342        for t in ('node', 'lan'):
343            if d.has_key(t): 
344                for x in d[t]:
345                    str += "<%s>" % t
346                    for k in x.keys():
347                        str += "<%s>%s</%s>" % (k, x[k],k)
348                    str += "</%s>\n" % t
349        str+= "</%s>" % self.xml
350        print >>out, str
351
352    def __call__(self):
353        """
354        The control flow.  Compose the request and print the response.
355        """
356        # Process the options using the customized option parser defined above
357        parser = fedd_exp_data_opts()
358
359        (opts, args) = parser.parse_args()
360
361        if opts.trusted != None:
362            if ( not os.access(opts.trusted, os.R_OK) ) :
363                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
364        else:
365            parser.error("--trusted is required")
366
367        if opts.debug > 0: opts.tracefile=sys.stderr
368
369        if opts.cert != None: cert = opts.cert
370
371        if cert == None:
372            sys.exit("No certificate given (--cert) or found")
373
374        if os.access(cert, os.R_OK):
375            fid = fedid(file=cert)
376        else:
377            sys.exit("Cannot read certificate (%s)" % cert)
378
379        if opts.exp_name and opts.exp_certfile:
380            sys.exit("Only one of --experiment_cert and " +\
381                    "--experiment_name permitted");
382
383        if opts.exp_certfile:
384            exp_id = { 'fedid': fedid(file=opts.exp_certfile) }
385
386        if opts.exp_name:
387            exp_id = { 'localname' : opts.exp_name }
388
389        req = { 'experiment': exp_id }
390
391        try:
392            resp_dict = self.do_rpc(req,
393                    opts.url, opts.transport, cert, opts.trusted, 
394                    serialize_only=opts.serialize_only,
395                    tracefile=opts.tracefile)
396        except self.RPCException, e:
397            exit_with_fault(\
398                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
399        except RuntimeError, e:
400            print e
401            sys.exit("Error processing RPC: %s" % e)
402
403        if getattr(self, 'key', None):
404            try:
405                if resp_dict.has_key(self.key):
406                    self.print_xml(resp_dict[self.key])
407            except RuntimeError, e:
408                sys.exit("Bad response. %s" % e.message)
409        else:
410            print resp_dict
411
412class terminate(fedd_rpc):
413    def __init__(self): 
414        """
415        Termination request
416        """
417
418        fedd_rpc.__init__(self, "Terminate")
419
420    def __call__(self):
421        """
422        The control flow.  Compose the request and print the response.
423        """
424        # Process the options using the customized option parser defined above
425        parser = fedd_exp_data_opts()
426
427        (opts, args) = parser.parse_args()
428
429        if opts.trusted != None:
430            if ( not os.access(opts.trusted, os.R_OK) ) :
431                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
432        else:
433            parser.error("--trusted is required")
434
435        if opts.debug > 0: opts.tracefile=sys.stderr
436
437        if opts.cert != None: cert = opts.cert
438
439        if cert == None:
440            sys.exit("No certificate given (--cert) or found")
441
442        if os.access(cert, os.R_OK):
443            fid = fedid(file=cert)
444        else:
445            sys.exit("Cannot read certificate (%s)" % cert)
446
447        if opts.exp_name and opts.exp_certfile:
448            sys.exit("Only one of --experiment_cert and " +\
449                    "--experiment_name permitted");
450
451        if opts.exp_certfile:
452            exp_id = { 'fedid': fedid(file=opts.exp_certfile) }
453
454        if opts.exp_name:
455            exp_id = { 'localname' : opts.exp_name }
456
457        req = { 'experiment': exp_id }
458
459        try:
460            resp_dict = self.do_rpc(req,
461                    opts.url, opts.transport, cert, opts.trusted, 
462                    serialize_only=opts.serialize_only,
463                    tracefile=opts.tracefile)
464        except self.RPCException, e:
465            exit_with_fault(\
466                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
467        except RuntimeError, e:
468            print e
469            sys.exit("Error processing RPC: %s" % e)
470
471        eid = resp_dict.get('experimentID', None)
472        if eid:
473            for id in eid:
474                for k in id.keys():
475                    if k == 'fedid': print "%s: %s" % (k,fedid(bits=id[k]))
476                    else: print "%s: %s" % (k, id[k])
477
478class create(fedd_rpc):
479    def __init__(self): 
480        fedd_rpc.__init__(self, "Create")
481    def __call__(self):
482        access_keys = []
483        # Process the options using the customized option parser defined above
484        parser = fedd_create_opts(access_keys, self.add_ssh_key,
485                self.add_x509_cert)
486
487        (opts, args) = parser.parse_args()
488
489        if opts.trusted != None:
490            if ( not os.access(opts.trusted, os.R_OK) ) :
491                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
492        else:
493            parser.error("--trusted is required")
494
495        if opts.debug > 0: opts.tracefile=sys.stderr
496
497        (user, cert) = self.get_user_info(access_keys)
498
499        if opts.user: user = opts.user
500
501        if opts.cert != None: cert = opts.cert
502
503        if cert == None:
504            sys.exit("No certificate given (--cert) or found")
505
506        if os.access(cert, os.R_OK):
507            fid = fedid(file=cert)
508            if opts.use_fedid == True:
509                user = fid
510        else:
511            sys.exit("Cannot read certificate (%s)" % cert)
512
513        if opts.file:
514            exp_desc = ""
515            try:
516                f = open(opts.file, 'r')
517                for line in f:
518                    exp_desc += line
519                f.close()
520            except IOError:
521                sys.exit("Cannot read description file (%s)" %opts.file)
522        else:
523            sys.exit("Must specify an experiment description (--file)")
524
525        if not opts.master:
526            sys.exit("Must specify a master testbed (--master)")
527
528        out_certfile = opts.out_certfile
529
530        msg = {
531                'experimentdescription': { 'ns2description': exp_desc },
532                'master': opts.master,
533                'user' : [ {\
534                        'userID': pack_id(user), \
535                        'access': [ { a.type: a.buf } for a in access_keys]\
536                        } ]
537                }
538
539        if opts.exp_name:
540            msg['experimentID'] = { 'localname': opts.exp_name }
541
542        if opts.debug > 1: print >>sys.stderr, msg
543
544        try:
545            resp_dict = self.do_rpc(msg, 
546                    opts.url, opts.transport, cert, opts.trusted, 
547                    serialize_only=opts.serialize_only,
548                    tracefile=opts.tracefile)
549        except self.RPCException, e:
550            exit_with_fault(\
551                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
552        except RuntimeError, e:
553            sys.exit("Error processing RPC: %s" % e)
554
555        if opts.debug > 1: print >>sys.stderr, resp_dict
556
557        ea = resp_dict.get('experimentAccess', None)
558        if out_certfile and ea and ea.has_key('X509'):
559            try:
560                f = open(out_certfile, "w")
561                print >>f, ea['X509']
562                f.close()
563            except IOError:
564                sys.exit('Could not write to %s' %  out_certfile)
565        eid = resp_dict.get('experimentID', None)
566        if eid:
567            for id in eid:
568                for k in id.keys():
569                    print "%s: %s" % (k, id[k])
570
571class split(fedd_rpc):
572    def __init__(self): 
573        fedd_rpc.__init__(self, "Ns2Split")
574    def __call__(self):
575        access_keys = []
576        # Process the options using the customized option parser defined above
577        parser = fedd_split_opts(access_keys, self.add_ssh_key,
578                self.add_x509_cert)
579
580        (opts, args) = parser.parse_args()
581
582        if opts.trusted != None:
583            if ( not os.access(opts.trusted, os.R_OK) ) :
584                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
585        else:
586            parser.error("--trusted is required")
587
588        if opts.debug > 0: opts.tracefile=sys.stderr
589
590        if opts.cert != None: cert = opts.cert
591        else: cert = None
592
593        if cert == None:
594            sys.exit("No certificate given (--cert) or found")
595
596        if os.access(cert, os.R_OK):
597            fid = fedid(file=cert)
598            if opts.use_fedid == True:
599                user = fid
600        else:
601            sys.exit("Cannot read certificate (%s)" % cert)
602
603        if opts.file:
604            exp_desc = ""
605            try:
606                f = open(opts.file, 'r')
607                for line in f:
608                    exp_desc += line
609                f.close()
610            except IOError:
611                sys.exit("Cannot read description file (%s)" %opts.file)
612        else:
613            sys.exit("Must specify an experiment description (--file)")
614
615        if not opts.master:
616            sys.exit("Must specify a master testbed (--master)")
617
618        out_certfile = opts.out_certfile
619
620        msg = {
621                'description': { 'ns2description': exp_desc },
622                'master': opts.master,
623                'include_fedkit': opts.fedkit,
624                }
625
626        if opts.debug > 1: print >>sys.stderr, msg
627
628        try:
629            resp_dict = self.do_rpc(msg, 
630                    opts.url, opts.transport, cert, opts.trusted, 
631                    serialize_only=opts.serialize_only,
632                    tracefile=opts.tracefile)
633        except self.RPCException, e:
634            exit_with_fault(\
635                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
636        except RuntimeError, e:
637            sys.exit("Error processing RPC: %s" % e)
638
639        if opts.debug > 1: print >>sys.stderr, resp_dict
640
641        out = resp_dict.get('output', None)
642
643        for line in out.splitlines():
644            print "%s" % line
645
646class access(fedd_rpc):
647    def __init__(self):
648        fedd_rpc.__init__(self, "RequestAccess")
649
650    def print_response_as_testbed(self, resp, label, out=sys.stdout):
651        """Print the response as input to the splitter script"""
652
653        e = resp['emulab']
654        p = e['project']
655        fields = { 
656                "Boss": e['boss'],
657                "OpsNode": e['ops'],
658                "Domain": e['domain'],
659                "FileServer": e['fileServer'],
660                "EventServer": e['eventServer'],
661                "Project": unpack_id(p['name'])
662                }
663        if (label != None): print >> out, "[%s]" % label
664
665        for l, v in fields.iteritems():
666            print >>out, "%s: %s" % (l, v)
667
668        for u in p['user']:
669            print >>out, "User: %s" % unpack_id(u['userID'])
670
671        for a in e['fedAttr']:
672            print >>out, "%s: %s" % (a['attribute'], a['value'])
673
674    def __call__(self):
675        access_keys = []
676        node_descs = []
677        proj = None
678
679        # Process the options using the customized option parser defined above
680        parser = fedd_access_opts(access_keys, node_descs, self.add_ssh_key,
681                self.add_x509_cert, self.add_node_desc)
682
683        (opts, args) = parser.parse_args()
684
685        if opts.testbed == None:
686            parser.error("--testbed is required")
687
688        if opts.trusted != None:
689            if ( not os.access(opts.trusted, os.R_OK) ) :
690                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
691        else:
692            parser.error("--trusted is required")
693
694        if opts.debug > 0: opts.tracefile=sys.stderr
695
696        (user, cert) = self.get_user_info(access_keys)
697
698        if opts.user: user = opts.user
699
700        if opts.cert != None: cert = opts.cert
701
702        if cert == None:
703            sys.exit("No certificate given (--cert) or found")
704
705        if os.access(cert, os.R_OK):
706            fid = fedid(file=cert)
707            if opts.use_fedid == True:
708                user = fid
709        else:
710            sys.exit("Cannot read certificate (%s)" % cert)
711
712        msg = {
713                'allocID': pack_id('test alloc'),
714                'destinationTestbed': pack_id(opts.testbed),
715                'serviceAccess' : [ { a.type: a.buf } for a in access_keys ],
716                'createAccess' : [ { a.type: a.buf } for a in access_keys ],
717                }
718
719        if len(node_descs) > 0:
720            msg['resources'] = { 
721                    'node': [ 
722                        { 
723                            'image':  n.image ,
724                            'hardware':  n.hardware,
725                            'count': n.count,
726                        } for n in node_descs],
727                    }
728
729        if opts.project != None:
730            if not opts.anonymous and user != None:
731                msg['project'] = {
732                        'name': pack_id(opts.project),
733                        'user': [ { 'userID': pack_id(user) } ],
734                        }
735            else:
736                msg['project'] = { 'name': pack_id(opts.project) }
737        else:
738            if not opts.anonymous and user != None:
739                msg['user'] = [ { 'userID': pack_id(user) } ]
740            else:
741                msg['user'] = [];
742
743        if opts.debug > 1: print >>sys.stderr, msg
744
745        try:
746            resp_dict = self.do_rpc(msg, 
747                    opts.url, opts.transport, cert, opts.trusted, 
748                    serialize_only=opts.serialize_only,
749                    tracefile=opts.tracefile)
750        except self.RPCException, e:
751            exit_with_fault(\
752                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
753        except RuntimeError, e:
754            sys.exit("Error processing RPC: %s" % e.message)
755
756        if opts.debug > 1: print >>sys.stderr, resp_dict
757        self.print_response_as_testbed(resp_dict, opts.label)
758
759cmds = {\
760        'create': create(),\
761        'split': split(),\
762        'access': access(),\
763        'vtopo': exp_data('Vtopo'),\
764        'vis': exp_data('Vis'),\
765        'info': exp_data('Info'),\
766        'terminate': terminate(),\
767    }
768
769operation = cmds.get(sys.argv[1], None)
770if operation:
771    del sys.argv[1]
772    operation()
773else:
774    sys.exit("Bad command: %s.  Valid ones are: %s" % \
775            (sys.argv[1], ", ".join(cmds.keys())))
776
Note: See TracBrowser for help on using the repository browser.