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
RevLine 
[6ff0b91]1#!/usr/local/bin/python
2
3import sys
4import os
5import pwd
6
7from fedd_services import *
[f4f4117]8from fedd_internal_services import *
[6ff0b91]9
10from M2Crypto import SSL, X509
[329f61d]11from M2Crypto.m2xmlrpclib import SSL_Transport
[6ff0b91]12import M2Crypto.httpslib
[329f61d]13
14from xmlrpclib import ServerProxy, Error, dumps, loads
[8f91e66]15from ZSI import SoapWriter
[bb3769a]16from ZSI.TC import QName, String, URI, AnyElement, UNBOUNDED, Any
17from ZSI.wstools.Namespaces import SOAP
18from ZSI.fault import FaultType, Detail
[6ff0b91]19
[2d58549]20import xmlrpclib
21
[2106ed1]22from fedd_util import fedid, fedd_ssl_context, pack_soap, unpack_soap, \
[03e0290]23        pack_id, unpack_id, encapsulate_binaries, decapsulate_binaries
[6ff0b91]24
25from optparse import OptionParser, OptionValueError
26
[bb3769a]27import parse_detail
28
[6ff0b91]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", 
[03e0290]82                default=0, help="Set debug.  Repeat for more information")
[8f91e66]83        self.add_option("-s", "--serializeOnly", action="store_true", 
[03e0290]84                dest="serialize_only", default=False,
[8f91e66]85                help="Print the SOAP request that would be sent and exit")
[6ff0b91]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",
[03e0290]89                type="string",default="https://localhost:23235", 
[6ff0b91]90                help="URL to connect to (default %default)")
[329f61d]91        self.add_option("-x","--transport", action="store", type="choice",
[03e0290]92                choices=("xmlrpc", "soap"), default="soap",
[329f61d]93                help="Transport for request (xmlrpc|soap) (Default: %default)")
[6ff0b91]94        self.add_option("--trace", action="store_const", dest="tracefile", 
95                const=sys.stderr, help="Print SOAP exchange to stderr")
96
[03e0290]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")
[e40c7ee]103        self.add_option("-E", "--experiment_name", dest="exp_name",
104                type="string", help="output certificate file")
[03e0290]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")
[6ff0b91]124
[03e0290]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)")
[6ff0b91]145
[e40c7ee]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
[0c0b13c]154def exit_with_fault(dict, out=sys.stderr):
155    """ Print an error message and exit.
156
[2d5c8b6]157    The dictionary contains the FeddFaultBody elements."""
[0c0b13c]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))
[03e0290]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)
[e40c7ee]177            self.code = fb.get('code', -1)
[03e0290]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)
[f4f4117]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)
[03e0290]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)
[6ff0b91]284
[03e0290]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)
[6ff0b91]323
[03e0290]324            try:
325                method_call = getattr(port, self.method, None)
326                resp = method_call(
[e40c7ee]327                        encapsulate_binaries({ self.RequestBody: req_dict},\
[03e0290]328                            ('fedid',)))
329            except Error, e:
330                resp = { 'FeddFaultBody': \
[0b466d1]331                        { 'errstr' : getattr(e, "faultCode", "No fault code"),
332                        'desc' : getattr(e, "faultString", "No fault string") }\
333                        }
[03e0290]334            if resp:
335                if resp.has_key(self.ResponseBody): 
[e40c7ee]336                    return decapsulate_binaries(resp[self.ResponseBody],
337                            ('fedid',))
[03e0290]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'
[c52c48d]362        elif op == 'Info': pass
[03e0290]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")
[6ff0b91]395
[03e0290]396        if opts.debug > 0: opts.tracefile=sys.stderr
[6ff0b91]397
[03e0290]398        if opts.cert != None: cert = opts.cert
[6ff0b91]399
[03e0290]400        if cert == None:
401            sys.exit("No certificate given (--cert) or found")
[6ff0b91]402
[03e0290]403        if os.access(cert, os.R_OK):
404            fid = fedid(file=cert)
405        else:
406            sys.exit("Cannot read certificate (%s)" % cert)
407
[e40c7ee]408        if opts.exp_name and opts.exp_certfile:
409            sys.exit("Only one of --experiment_cert and " +\
410                    "--experiment_name permitted");
411
[03e0290]412        if opts.exp_certfile:
[e40c7ee]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 }
[03e0290]419
420        try:
[e40c7ee]421            resp_dict = self.do_rpc(req,
[03e0290]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:
[e40c7ee]429            print e
430            sys.exit("Error processing RPC: %s" % e)
[03e0290]431
[c52c48d]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
[03e0290]440
[7a8d667]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
[03e0290]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 = {
[3925b50]560                'experimentdescription': { 'ns2description': exp_desc },
[03e0290]561                'master': opts.master,
562                'user' : [ {\
563                        'userID': pack_id(user), \
564                        'access': [ { a.type: a.buf } for a in access_keys]\
565                        } ]
[6ff0b91]566                }
[03e0290]567
[e40c7ee]568        if opts.exp_name:
569            msg['experimentID'] = { 'localname': opts.exp_name }
570
[03e0290]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:
[0b466d1]582            sys.exit("Error processing RPC: %s" % e)
[03e0290]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'):
[0c0b13c]588            try:
[03e0290]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)
[e40c7ee]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])
[03e0290]600
[f4f4117]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
[03e0290]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),
[72ed6e4]743                'serviceAccess' : [ { a.type: a.buf } for a in access_keys ],
744                'createAccess' : [ { a.type: a.buf } for a in access_keys ],
[03e0290]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(),\
[f4f4117]789        'split': split(),\
[03e0290]790        'access': access(),\
791        'vtopo': exp_data('Vtopo'),\
792        'vis': exp_data('Vis'),\
[c52c48d]793        'info': exp_data('Info'),\
[7a8d667]794        'terminate': terminate(),\
[03e0290]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.