source: fedd/fedd_client.py @ f4f4117

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

add remote splitter interface

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