source: fedd/fedd_client.py @ 0e41546

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

More namespace cleanup

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