source: fedd/fedd_client.py @ ec4fb42

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

Clean up some names that start with fedd_ that are ugly with the new package
structure. A couple other bugs cleaned up, too.

  • Property mode set to 100755
File size: 22.2 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 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 fedd.fedid import fedid
23from fedd.remote_service import service_caller
24from fedd.service_error import *
25import fedd.parse_detail
26
27from optparse import OptionParser, OptionValueError
28
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        self.add_option("-p", "--project", action="store", dest="project", 
112                type="string",
113                help="Project to export from master")
114        if add_key_callback:
115            self.add_option("-k", "--sshKey", action="callback", type="string", 
116                    callback=add_key_callback, callback_args=(access_keys,),
117                    help="ssh key for access (can be supplied more than once")
118        if add_cert_callback:
119            self.add_option("-K", "--x509Key", action="callback",
120                    type="string", callback=add_cert_callback,
121                    callback_args=(access_keys,),
122                    help="X509 certificate for access " + \
123                        "(can be supplied more than once")
124        self.add_option("-m", "--master", dest="master",
125                help="Master testbed in the federation")
126        self.add_option("-U", "--username", action="store", dest="user",
127                type="string", help="Use this username instead of the uid")
128
129class fedd_split_opts(fedd_create_opts):
130    def __init__(self, access_keys, add_key_callback=None, 
131            add_cert_callback=None):
132        fedd_create_opts.__init__(self, access_keys, add_key_callback,
133                add_cert_callback)
134        self.add_option('-t','--fedkit', action='store_true', dest='fedkit',
135                default=False,
136                help="get output suitable for federation kit install")
137
138
139class fedd_access_opts(fedd_create_opts):
140    def __init__(self, access_keys, node_descs, add_key_callback=None, 
141            add_cert_callback=None, add_node_callback=None):
142        fedd_create_opts.__init__(self, access_keys, add_key_callback,
143                add_cert_callback)
144        self.add_option("-a","--anonymous", action="store_true",
145                dest="anonymous", default=False,
146                help="Do not include a user in the request")
147        self.add_option("-l","--label", action="store", dest="label",
148                type="string", help="Label for output")
149        if add_node_callback:
150            self.add_option("-n", "--node", action="callback", type="string", 
151                    callback=add_node_callback, callback_args=(node_descs,),
152                    help="Node description: image:hardware[:count]")
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 not opts.project :
496            parser.error('--project is required')
497
498        if opts.debug > 0: opts.tracefile=sys.stderr
499
500        (user, cert) = self.get_user_info(access_keys)
501
502        if opts.user: user = opts.user
503
504        if opts.cert != None: cert = opts.cert
505
506        if cert == None:
507            sys.exit("No certificate given (--cert) or found")
508
509        if os.access(cert, os.R_OK):
510            fid = fedid(file=cert)
511            if opts.use_fedid == True:
512                user = fid
513        else:
514            sys.exit("Cannot read certificate (%s)" % cert)
515
516        if opts.file:
517            exp_desc = ""
518            try:
519                f = open(opts.file, 'r')
520                for line in f:
521                    exp_desc += line
522                f.close()
523            except IOError:
524                sys.exit("Cannot read description file (%s)" %opts.file)
525        else:
526            sys.exit("Must specify an experiment description (--file)")
527
528        if not opts.master:
529            sys.exit("Must specify a master testbed (--master)")
530
531        out_certfile = opts.out_certfile
532
533        msg = {
534                'experimentdescription': { 'ns2description': exp_desc },
535                'master': opts.master,
536                'exportProject': { 'localname': opts.project },
537                'user' : [ {\
538                        'userID': pack_id(user), \
539                        'access': [ { a.type: a.buf } for a in access_keys]\
540                        } ]
541                }
542
543        if opts.exp_name:
544            msg['experimentID'] = { 'localname': opts.exp_name }
545
546        if opts.debug > 1: print >>sys.stderr, msg
547
548        try:
549            resp_dict = self.do_rpc(msg, 
550                    opts.url, opts.transport, cert, opts.trusted, 
551                    serialize_only=opts.serialize_only,
552                    tracefile=opts.tracefile)
553        except self.RPCException, e:
554            exit_with_fault(\
555                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
556        except RuntimeError, e:
557            sys.exit("Error processing RPC: %s" % e)
558
559        if opts.debug > 1: print >>sys.stderr, resp_dict
560
561        ea = resp_dict.get('experimentAccess', None)
562        if out_certfile and ea and ea.has_key('X509'):
563            try:
564                f = open(out_certfile, "w")
565                print >>f, ea['X509']
566                f.close()
567            except IOError:
568                sys.exit('Could not write to %s' %  out_certfile)
569        eid = resp_dict.get('experimentID', None)
570        if eid:
571            for id in eid:
572                for k in id.keys():
573                    print "%s: %s" % (k, id[k])
574
575class split(fedd_rpc):
576    def __init__(self): 
577        fedd_rpc.__init__(self, "Ns2Split")
578    def __call__(self):
579        access_keys = []
580        # Process the options using the customized option parser defined above
581        parser = fedd_split_opts(access_keys, self.add_ssh_key,
582                self.add_x509_cert)
583
584        (opts, args) = parser.parse_args()
585
586        if opts.trusted != None:
587            if ( not os.access(opts.trusted, os.R_OK) ) :
588                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
589        else:
590            parser.error("--trusted is required")
591
592        if opts.debug > 0: opts.tracefile=sys.stderr
593
594        if opts.cert != None: cert = opts.cert
595        else: cert = None
596
597        if cert == None:
598            sys.exit("No certificate given (--cert) or found")
599
600        if os.access(cert, os.R_OK):
601            fid = fedid(file=cert)
602            if opts.use_fedid == True:
603                user = fid
604        else:
605            sys.exit("Cannot read certificate (%s)" % cert)
606
607        if opts.file:
608            exp_desc = ""
609            try:
610                f = open(opts.file, 'r')
611                for line in f:
612                    exp_desc += line
613                f.close()
614            except IOError:
615                sys.exit("Cannot read description file (%s)" %opts.file)
616        else:
617            sys.exit("Must specify an experiment description (--file)")
618
619        if not opts.master:
620            sys.exit("Must specify a master testbed (--master)")
621
622        out_certfile = opts.out_certfile
623
624        msg = {
625                'description': { 'ns2description': exp_desc },
626                'master': opts.master,
627                'include_fedkit': opts.fedkit,
628                }
629
630        if opts.debug > 1: print >>sys.stderr, msg
631
632        try:
633            resp_dict = self.do_rpc(msg, 
634                    opts.url, opts.transport, cert, opts.trusted, 
635                    serialize_only=opts.serialize_only,
636                    tracefile=opts.tracefile)
637        except self.RPCException, e:
638            exit_with_fault(\
639                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
640        except RuntimeError, e:
641            sys.exit("Error processing RPC: %s" % e)
642
643        if opts.debug > 1: print >>sys.stderr, resp_dict
644
645        out = resp_dict.get('output', None)
646
647        for line in out.splitlines():
648            print "%s" % line
649
650class access(fedd_rpc):
651    def __init__(self):
652        fedd_rpc.__init__(self, "RequestAccess")
653
654    def print_response_as_testbed(self, resp, label, out=sys.stdout):
655        """Print the response as input to the splitter script"""
656
657        e = resp['emulab']
658        p = e['project']
659        fields = { 
660                "Boss": e['boss'],
661                "OpsNode": e['ops'],
662                "Domain": e['domain'],
663                "FileServer": e['fileServer'],
664                "EventServer": e['eventServer'],
665                "Project": unpack_id(p['name'])
666                }
667        if (label != None): print >> out, "[%s]" % label
668
669        for l, v in fields.iteritems():
670            print >>out, "%s: %s" % (l, v)
671
672        for u in p['user']:
673            print >>out, "User: %s" % unpack_id(u['userID'])
674
675        for a in e['fedAttr']:
676            print >>out, "%s: %s" % (a['attribute'], a['value'])
677
678    def __call__(self):
679        access_keys = []
680        node_descs = []
681        proj = None
682
683        # Process the options using the customized option parser defined above
684        parser = fedd_access_opts(access_keys, node_descs, self.add_ssh_key,
685                self.add_x509_cert, self.add_node_desc)
686
687        (opts, args) = parser.parse_args()
688
689        if opts.testbed == None:
690            parser.error("--testbed is required")
691
692        if opts.trusted != None:
693            if ( not os.access(opts.trusted, os.R_OK) ) :
694                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
695        else:
696            parser.error("--trusted is required")
697
698        if opts.debug > 0: opts.tracefile=sys.stderr
699
700        (user, cert) = self.get_user_info(access_keys)
701
702        if opts.user: user = opts.user
703
704        if opts.cert != None: cert = opts.cert
705
706        if cert == None:
707            sys.exit("No certificate given (--cert) or found")
708
709        if os.access(cert, os.R_OK):
710            fid = fedid(file=cert)
711            if opts.use_fedid == True:
712                user = fid
713        else:
714            sys.exit("Cannot read certificate (%s)" % cert)
715
716        msg = {
717                'allocID': pack_id('test alloc'),
718                'destinationTestbed': pack_id(opts.testbed),
719                'serviceAccess' : [ { a.type: a.buf } for a in access_keys ],
720                'createAccess' : [ { a.type: a.buf } for a in access_keys ],
721                }
722
723        if len(node_descs) > 0:
724            msg['resources'] = { 
725                    'node': [ 
726                        { 
727                            'image':  n.image ,
728                            'hardware':  n.hardware,
729                            'count': n.count,
730                        } for n in node_descs],
731                    }
732
733        if opts.project != None:
734            if not opts.anonymous and user != None:
735                msg['project'] = {
736                        'name': pack_id(opts.project),
737                        'user': [ { 'userID': pack_id(user) } ],
738                        }
739            else:
740                msg['project'] = { 'name': pack_id(opts.project) }
741        else:
742            if not opts.anonymous and user != None:
743                msg['user'] = [ { 'userID': pack_id(user) } ]
744            else:
745                msg['user'] = [];
746
747        if opts.debug > 1: print >>sys.stderr, msg
748
749        try:
750            resp_dict = self.do_rpc(msg, 
751                    opts.url, opts.transport, cert, opts.trusted, 
752                    serialize_only=opts.serialize_only,
753                    tracefile=opts.tracefile)
754        except self.RPCException, e:
755            exit_with_fault(\
756                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
757        except RuntimeError, e:
758            sys.exit("Error processing RPC: %s" % e.message)
759
760        if opts.debug > 1: print >>sys.stderr, resp_dict
761        self.print_response_as_testbed(resp_dict, opts.label)
762
763cmds = {\
764        'create': create(),\
765        'split': split(),\
766        'access': access(),\
767        'vtopo': exp_data('Vtopo'),\
768        'vis': exp_data('Vis'),\
769        'info': exp_data('Info'),\
770        'terminate': terminate(),\
771    }
772
773operation = cmds.get(sys.argv[1], None)
774if operation:
775    del sys.argv[1]
776    operation()
777else:
778    sys.exit("Bad command: %s.  Valid ones are: %s" % \
779            (sys.argv[1], ", ".join(cmds.keys())))
780
Note: See TracBrowser for help on using the repository browser.