#!/usr/local/bin/python import sys import re from federation.remote_service import service_caller from federation.client_lib import client_opts, exit_with_fault, RPCException, \ wrangle_standard_options, do_rpc, get_experiment_names, save_certfile class fedd_create_opts(client_opts): """ Extra options that create needs. Help entries should explain them. """ def __init__(self): client_opts.__init__(self) self.add_option("--experiment_cert", dest="out_certfile", type="string", help="output certificate file") self.add_option("--experiment_name", dest="exp_name", type="string", help="Suggested experiment name") self.add_option("--file", dest="file", help="experiment description file") self.add_option("--project", action="store", dest="project", type="string", help="Project to export from master") self.add_option("--master", dest="master", help="Master testbed in the federation (pseudo project export)") self.add_option("--service", dest="service", action="append", type="string", default=[], help="Service description name:exporters:importers:attrs") self.add_option("--map", dest="map", action="append", type="string", default=[], help="Explicit map from testbed label to URI - " + \ "deter:https://users.isi.deterlab/net:13232") def parse_service(svc): """ Pasre a service entry into a hash representing a service entry in a message. The format is: svc_name:exporter(s):importer(s):attr=val,attr=val The svc_name is teh service name, exporter is the exporting testbeds (comma-separated) importer is the importing testbeds (if any) and the rest are attr=val pairs that will become attributes of the service. These include parameters and other such stuff. """ terms = svc.split(':') svcd = { } if len(terms) < 2 or len(terms[0]) == 0 or len(terms[1]) == 0: sys.exit("Bad service description '%s': Not enough terms" % svc) svcd['name'] = terms[0] svcd['export'] = terms[1].split(",") if len(terms) > 2 and len(terms[2]) > 0: svcd['import'] = terms[2].split(",") if len(terms) > 3 and len(terms[3]) > 0: svcd['fedAttr'] = [ ] for t in terms[3].split(";"): i = t.find("=") if i != -1 : svcd['fedAttr'].append( {'attribute': t[0:i], 'value': t[i+1:]}) else: sys.exit("Bad service attribute '%s': no equals sign" % t) return svcd def project_export_service(master, project): """ Output the dict representation of a project_export service for this project and master. """ return { 'name': 'project_export', 'export': [master], 'importall': True, 'fedAttr': [ { 'attribute': 'project', 'value': project }, ], } # Main line service_re = re.compile('^\\s*#\\s*SERVICE:\\s*([\\S]+)') parser = fedd_create_opts() (opts, args) = parser.parse_args() cert, fid, url = wrangle_standard_options(opts) if opts.file: try: lines = [ line for line in open(opts.file, 'r')] exp_desc = "".join(lines) except EnvironmentError: sys.exit("Cannot read description file (%s)" %opts.file) else: sys.exit("Must specify an experiment description (--file)") out_certfile = opts.out_certfile # Fill in services svcs = [] if opts.master and opts.project: svcs.append(project_export_service(opts.master, opts.project)) svcs.extend([ parse_service(s) for s in opts.service]) # Parse all the strings that we can pull out of the file using the service_re. svcs.extend([parse_service(service_re.match(l).group(1)) \ for l in lines if service_re.match(l)]) # Create a testbed map if one is specified tbmap = { } for m in opts.map: i = m.find(":") if i != -1: tbmap[m[0:i]] = m[i+1:] else: sys.exit("Bad mapping argument: %s" %m ) if not svcs: print >>sys.stderr, "Warning:Neither master/project nor services requested" msg = { } if opts.exp_name: msg['experimentID'] = { 'localname': opts.exp_name } if opts.debug > 1: print >>sys.stderr, msg try: resp_dict = do_rpc(msg, url, opts.transport, cert, opts.trusted, serialize_only=opts.serialize_only, tracefile=opts.tracefile, caller=service_caller('New'), responseBody="NewResponseBody") except RPCException, e: exit_with_fault(e) except RuntimeError, e: sys.exit("Error processing RPC: %s" % e) if opts.debug > 1: print >>sys.stderr, resp_dict try: save_certfile(opts.out_certfile, resp_dict.get('experimentAccess', None)) except EnvironmentError, e: sys.exit('Could not write to %s: %s' % (opts.out_certfile, e)) e_fedid, e_local = get_experiment_names(resp_dict.get('experimentID', None)) if not e_fedid and not e_local and opts.serialize_only: e_local = "serialize" msg = { 'experimentdescription': { 'ns2description': exp_desc }, } if svcs: msg['service'] = svcs if e_fedid: msg['experimentID'] = { 'fedid': e_fedid } elif e_local: msg['experimentID'] = { 'localname': e_local } else: sys.exit("New did not return an experiment ID??") if tbmap: msg['testbedmap'] = [ { 'testbed': t, 'uri': u } for t, u in tbmap.items() ] if opts.debug > 1: print >>sys.stderr, msg try: resp_dict = do_rpc(msg, url, opts.transport, cert, opts.trusted, serialize_only=opts.serialize_only, tracefile=opts.tracefile, caller=service_caller('Create'), responseBody="CreateResponseBody") except RPCException, e: exit_with_fault(e) except RuntimeError, e: sys.exit("Error processing RPC: %s" % e) if opts.debug > 1: print >>sys.stderr, resp_dict e_fedid, e_local = get_experiment_names(resp_dict.get('experimentID', None)) st = resp_dict.get('experimentStatus', None) if e_local: print "localname: %s" % e_local if e_fedid: print "fedid: %s" % e_fedid if st: print "status: %s" % st