source: fedd/fedd_client.py @ 058f58e

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

Unify the code for calling SOAP and XMLRPC services into a couple classes.
Before there were slightly different semantics everywhere.

Also make the handlers classes rather than the output of stub compiling
functions.

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