source: fedd/fedd_client.py @ 2c6128f

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

Add support for a real fedkit tar file rather than the ad hoc script stuff.

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