X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fclient%2Fsfi.py;h=53d655b80adca14d36803968c5f086cb715b754f;hb=1cc8e9613cab8b5b22478de369f259e591c54e6d;hp=5d44cf3f3e081ed7533879f433d95327ad53e714;hpb=5da0dafa61565ae254d5e29cdd6b55310c204987;p=sfa.git diff --git a/sfa/client/sfi.py b/sfa/client/sfi.py index 5d44cf3f..53d655b8 100644 --- a/sfa/client/sfi.py +++ b/sfa/client/sfi.py @@ -46,30 +46,8 @@ from sfa.client.candidates import Candidates CM_PORT=12346 -# utility methods here -def optparse_listvalue_callback(option, option_string, value, parser): - setattr(parser.values, option.dest, value.split(',')) - -# a code fragment that could be helpful for argparse which unfortunately is -# available with 2.7 only, so this feels like too strong a requirement for the client side -#class ExtraArgAction (argparse.Action): -# def __call__ (self, parser, namespace, values, option_string=None): -# would need a try/except of course -# (k,v)=values.split('=') -# d=getattr(namespace,self.dest) -# d[k]=v -##### -#parser.add_argument ("-X","--extra",dest='extras', default={}, action=ExtraArgAction, -# help="set extra flags, testbed dependent, e.g. --extra enabled=true") - -def optparse_dictvalue_callback (option, option_string, value, parser): - try: - (k,v)=value.split('=',1) - d=getattr(parser.values, option.dest) - d[k]=v - except: - parser.print_help() - sys.exit(1) +from sfa.client.common import optparse_listvalue_callback, optparse_dictvalue_callback, \ + terminal_render, filter_records # display methods def display_rspec(rspec, format='rspec'): @@ -115,14 +93,15 @@ def filter_records(type, records): return filtered_records -def credential_printable (credential_string): - credential=Credential(string=credential_string) +def credential_printable (cred): + credential=Credential(cred=cred) result="" result += credential.get_summary_tostring() result += "\n" rights = credential.get_privileges() - result += "rights=%s"%rights - result += "\n" + result += "type=%s\n" % credential.type + result += "version=%s\n" % credential.version + result += "rights=%s\n"%rights return result def show_credentials (cred_s): @@ -197,39 +176,6 @@ def save_record_to_file(filename, record_dict): f.close() return -# used in sfi list -def terminal_render (records,options): - # sort records by type - grouped_by_type={} - for record in records: - type=record['type'] - if type not in grouped_by_type: grouped_by_type[type]=[] - grouped_by_type[type].append(record) - for (type, list) in grouped_by_type.items(): -# print 20 * '-', type - try: renderer=eval('terminal_render_'+type) - except: renderer=terminal_render_default - for record in list: renderer(record,options) - -def terminal_render_default (record,options): - print "%s (%s)" % (record['hrn'], record['type']) -def terminal_render_user (record, options): - print "%s (User)"%record['hrn'], - if record.get('reg-pi-authorities',None): print " [PI at %s]"%(" and ".join(record['reg-pi-authorities'])), - if record.get('reg-slices',None): print " [IN slices %s]"%(" and ".join(record['reg-slices'])), - print "" -def terminal_render_slice (record, options): - print "%s (Slice)"%record['hrn'], - if record.get('reg-researchers',None): print " [USERS %s]"%(" and ".join(record['reg-researchers'])), -# print record.keys() - print "" -def terminal_render_authority (record, options): - print "%s (Authority)"%record['hrn'], - if record.get('reg-pis',None): print " [PIS %s]"%(" and ".join(record['reg-pis'])), - print "" -def terminal_render_node (record, options): - print "%s (Node)"%record['hrn'] - # minimally check a key argument def check_ssh_key (key): good_ssh_key = r'^.*(?:ssh-dss|ssh-rsa)[ ]+[A-Za-z0-9+/=]+(?: .*)?$' @@ -313,22 +259,22 @@ class Sfi: ("version", ""), ("list", "authority"), ("show", "name"), - ("add", "record"), - ("update", "record"), + ("add", "[record]"), + ("update", "[record]"), ("remove", "name"), - ("slices", ""), - ("resources", "[slice_hrn]"), + ("resources", ""), + ("describe", "slice_hrn"), ("create", "slice_hrn rspec"), + ("allocate", "slice_hrn rspec"), + ("provision", "slice_hrn"), + ("action", "slice_hrn action"), ("delete", "slice_hrn"), ("status", "slice_hrn"), - ("start", "slice_hrn"), - ("stop", "slice_hrn"), - ("reset", "slice_hrn"), ("renew", "slice_hrn time"), ("shutdown", "slice_hrn"), ("get_ticket", "slice_hrn rspec"), ("redeem_ticket", "ticket"), - ("delegate", "name"), + ("delegate", "to_hrn"), ("gid", "[name]"), ("trusted", "cred"), ("config", ""), @@ -373,36 +319,29 @@ class Sfi: parser.add_option('-x', '--xrn', dest='xrn', metavar='', help='object hrn/urn (mandatory)') parser.add_option('-t', '--type', dest='type', metavar='', help='object type', default=None) parser.add_option('-e', '--email', dest='email', default="", help="email (mandatory for users)") -# use --extra instead -# parser.add_option('-u', '--url', dest='url', metavar='', default=None, help="URL, useful for slices") -# parser.add_option('-d', '--description', dest='description', metavar='', -# help='Description, useful for slices', default=None) parser.add_option('-k', '--key', dest='key', metavar='', help='public key string or file', default=None) - parser.add_option('-s', '--slices', dest='slices', metavar='', help='slice xrns', + parser.add_option('-s', '--slices', dest='slices', metavar='', help='Set/replace slice xrns', default='', type="str", action='callback', callback=optparse_listvalue_callback) parser.add_option('-r', '--researchers', dest='researchers', metavar='', - help='slice researchers', default='', type="str", action='callback', + help='Set/replace slice researchers', default='', type="str", action='callback', callback=optparse_listvalue_callback) - parser.add_option('-p', '--pis', dest='pis', metavar='', help='Principal Investigators/Project Managers', + parser.add_option('-p', '--pis', dest='pis', metavar='', help='Set/replace Principal Investigators/Project Managers', default='', type="str", action='callback', callback=optparse_listvalue_callback) -# use --extra instead -# parser.add_option('-f', '--firstname', dest='firstname', metavar='', help='user first name') -# parser.add_option('-l', '--lastname', dest='lastname', metavar='', help='user last name') parser.add_option ('-X','--extra',dest='extras',default={},type='str',metavar="", action="callback", callback=optparse_dictvalue_callback, nargs=1, help="set extra/testbed-dependent flags, e.g. --extra enabled=true") # user specifies remote aggregate/sm/component - if command in ("resources", "slices", "create", "delete", "start", "stop", - "restart", "shutdown", "get_ticket", "renew", "status"): + if command in ("resources", "describe", "allocate", "provision", "create", "delete", "allocate", "provision", + "action", "shutdown", "get_ticket", "renew", "status"): parser.add_option("-d", "--delegate", dest="delegate", default=None, action="store_true", help="Include a credential delegated to the user's root"+\ "authority in set of credentials for this call") # show_credential option - if command in ("list","resources","create","add","update","remove","slices","delete","status","renew"): + if command in ("list","resources", "describe", "provision", "allocate", "create","add","update","remove","slices","delete","status","renew"): parser.add_option("-C","--credential",dest='show_credential',action='store_true',default=False, help="show credential(s) used in human-readable form") # registy filter option @@ -414,7 +353,7 @@ class Sfi: if command in ("show"): parser.add_option("-k","--key",dest="keys",action="append",default=[], help="specify specific keys to be displayed from record") - if command in ("resources"): + if command in ("resources", "describe"): # rspec version parser.add_option("-r", "--rspec-version", dest="rspec_version", default="SFA 1", help="schema type and version of resulting RSpec") @@ -436,7 +375,7 @@ class Sfi: # 'create' does return the new rspec, makes sense to save that too - if command in ("resources", "show", "list", "gid", 'create'): + if command in ("resources", "describe", "allocate", "provision", "show", "list", "gid", 'create'): parser.add_option("-o", "--output", dest="file", help="output XML to file", metavar="FILE", default=None) @@ -451,12 +390,22 @@ class Sfi: if command == 'list': parser.add_option("-r", "--recursive", dest="recursive", action='store_true', help="list all child records", default=False) + parser.add_option("-v", "--verbose", dest="verbose", action='store_true', + help="gives details, like user keys", default=False) if command in ("delegate"): parser.add_option("-u", "--user", - action="store_true", dest="delegate_user", default=False, - help="delegate user credential") - parser.add_option("-s", "--slice", dest="delegate_slice", - help="delegate slice credential", metavar="HRN", default=None) + action="store_true", dest="delegate_user", default=False, + help="delegate your own credentials; default if no other option is provided") + parser.add_option("-s", "--slice", dest="delegate_slices",action='append',default=[], + metavar="slice_hrn", help="delegate cred. for slice HRN") + parser.add_option("-a", "--auths", dest='delegate_auths',action='append',default=[], + metavar='auth_hrn', help="delegate cred for auth HRN") + # this primarily is a shorthand for -a my_hrn^ + parser.add_option("-p", "--pi", dest='delegate_pi', default=None, action='store_true', + help="delegate your PI credentials, so s.t. like -a your_hrn^") + parser.add_option("-A","--to-authority",dest='delegate_to_authority',action='store_true',default=False, + help="""by default the mandatory argument is expected to be a user, +use this if you mean an authority instead""") if command in ("version"): parser.add_option("-R","--registry-version", @@ -687,6 +636,9 @@ class Sfi: # extract what's needed self.private_key = client_bootstrap.private_key() self.my_credential_string = client_bootstrap.my_credential_string () + self.my_credential = {'geni_type': 'geni_sfa', + 'geni_version': '3.0', + 'geni_value': self.my_credential_string} self.my_gid = client_bootstrap.my_gid () self.client_bootstrap = client_bootstrap @@ -697,9 +649,17 @@ class Sfi: sys.exit(-1) return self.client_bootstrap.authority_credential_string (self.authority) + def authority_credential_string(self, auth_hrn): + return self.client_bootstrap.authority_credential_string (auth_hrn) + def slice_credential_string(self, name): return self.client_bootstrap.slice_credential_string (name) + def slice_credential(self, name): + return {'geni_type': 'geni_sfa', + 'geni_version': '3.0', + 'geni_value': self.slice_credential_string(name)} + # xxx should be supported by sfaclientbootstrap as well def delegate_cred(self, object_cred, hrn, type='authority'): # the gid and hrn of the object we are delegating @@ -932,15 +892,22 @@ or version information about sfi itself return def add(self, options, args): - "add record into registry from xml file (Register)" + "add record into registry by using the command options (Recommended) or from xml file (Register)" auth_cred = self.my_authority_credential_string() if options.show_credential: show_credentials(auth_cred) record_dict = {} - if len(args) > 0: - record_filepath = args[0] - rec_file = self.get_record_file(record_filepath) - record_dict.update(load_record_from_file(rec_file).todict()) + if len(args) > 1: + self.print_help() + sys.exit(1) + if len(args)==1: + try: + record_filepath = args[0] + rec_file = self.get_record_file(record_filepath) + record_dict.update(load_record_from_file(rec_file).todict()) + except: + print "Cannot load record file %s"%record_filepath + sys.exit(1) if options: record_dict.update(load_record_from_opts(options).todict()) # we should have a type by now @@ -957,7 +924,7 @@ or version information about sfi itself return self.registry().Register(record_dict, auth_cred) def update(self, options, args): - "update record into registry from xml file (Update)" + "update record into registry by using the command options (Recommended) or from xml file (Update)" record_dict = {} if len(args) > 0: record_filepath = args[0] @@ -1020,12 +987,9 @@ or version information about sfi itself server = self.sliceapi() # creds creds = [self.my_credential_string] - if options.delegate: - delegated_cred = self.delegate_cred(self.my_credential_string, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} - api_options['call_id']=unique_call_id() + api_options['call_id']=unique_call_id() if options.show_credential: show_credentials(creds) result = server.ListSlices(creds, *self.ois(server,api_options)) @@ -1039,17 +1003,13 @@ or version information about sfi itself # show rspec for named slice def resources(self, options, args): """ - with no arg, discover available resources, (ListResources) + discover available resources or with an slice hrn, shows currently provisioned resources """ server = self.sliceapi() # set creds - creds = [] - if args: - creds.append(self.slice_credential_string(args[0])) - else: - creds.append(self.my_credential_string) + creds = [self.my_credential] if options.delegate: creds.append(self.delegate_cred(cred, get_authority(self.authority))) if options.show_credential: @@ -1062,9 +1022,6 @@ or with an slice hrn, shows currently provisioned resources api_options ['call_id'] = unique_call_id() # ask for cached value if available api_options ['cached'] = True - if args: - hrn = args[0] - api_options['geni_slice_urn'] = hrn_to_urn(hrn, 'slice') if options.info: api_options['info'] = options.info if options.list_leases: @@ -1095,6 +1052,45 @@ or with an slice hrn, shows currently provisioned resources return + def describe(self, options, args): + """ + Shows currently provisioned resources. + """ + server = self.sliceapi() + + # set creds + creds = [self.slice_credential(args[0])] + if options.delegate: + creds.append(self.delegate_cred(cred, get_authority(self.authority))) + if options.show_credential: + show_credentials(creds) + + api_options = {'call_id': unique_call_id(), + 'cached': True, + 'info': options.info, + 'list_leases': options.list_leases, + 'geni_rspec_version': {'type': 'geni', 'version': '3.0'}, + } + if options.rspec_version: + version_manager = VersionManager() + server_version = self.get_cached_server_version(server) + if 'sfa' in server_version: + # just request the version the client wants + api_options['geni_rspec_version'] = version_manager.get_version(options.rspec_version).to_dict() + else: + api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'} + urn = Xrn(args[0], type='slice').get_urn() + result = server.Describe([urn], creds, api_options) + value = ReturnValue.get_value(result) + if self.options.raw: + save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) + if options.file is not None: + save_rspec_to_file(value, options.file) + if (self.options.raw is None) and (options.file is None): + display_rspec(value, options.format) + + return + def create(self, options, args): """ create or update named slice with given rspec @@ -1137,7 +1133,8 @@ or with an slice hrn, shows currently provisioned resources # xxx Thierry 2012 sept. 21 # contrary to what I was first thinking, calling Resolve with details=False does not yet work properly here # I am turning details=True on again on a - hopefully - temporary basis, just to get this whole thing to work again - slice_records = self.registry().Resolve(slice_urn, [self.my_credential_string], {'details':True}) + slice_records = self.registry().Resolve(slice_urn, [self.my_credential_string]) + # slice_records = self.registry().Resolve(slice_urn, [self.my_credential_string], {'details':True}) if slice_records and 'reg-researchers' in slice_records[0] and slice_records[0]['reg-researchers']: slice_record = slice_records[0] user_hrns = slice_record['reg-researchers'] @@ -1155,8 +1152,6 @@ or with an slice hrn, shows currently provisioned resources # do not append users, keys, or slice tags. Anything # not contained in this request will be removed from the slice - # CreateSliver has supported the options argument for a while now so it should - # be safe to assume this server support it api_options = {} api_options ['append'] = False api_options ['call_id'] = unique_call_id() @@ -1182,25 +1177,116 @@ or with an slice hrn, shows currently provisioned resources slice_urn = hrn_to_urn(slice_hrn, 'slice') # creds - slice_cred = self.slice_credential_string(slice_hrn) + slice_cred = self.slice_credential(slice_hrn) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} api_options ['call_id'] = unique_call_id() if options.show_credential: show_credentials(creds) - result = server.DeleteSliver(slice_urn, creds, *self.ois(server, api_options ) ) + result = server.Delete([slice_urn], creds, *self.ois(server, api_options ) ) value = ReturnValue.get_value(result) if self.options.raw: save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) else: print value - return value - + return value + + def allocate(self, options, args): + server = self.sliceapi() + server_version = self.get_cached_server_version(server) + slice_hrn = args[0] + slice_urn = Xrn(slice_hrn, type='slice').get_urn() + + # credentials + creds = [self.slice_credential(slice_hrn)] + + delegated_cred = None + if server_version.get('interface') == 'slicemgr': + # delegate our cred to the slice manager + # do not delegate cred to slicemgr...not working at the moment + pass + #if server_version.get('hrn'): + # delegated_cred = self.delegate_cred(slice_cred, server_version['hrn']) + #elif server_version.get('urn'): + # delegated_cred = self.delegate_cred(slice_cred, urn_to_hrn(server_version['urn'])) + + if options.show_credential: + show_credentials(creds) + + # rspec + rspec_file = self.get_rspec_file(args[1]) + rspec = open(rspec_file).read() + api_options = {} + api_options ['call_id'] = unique_call_id() + result = server.Allocate(slice_urn, creds, rspec, api_options) + value = ReturnValue.get_value(result) + if self.options.raw: + save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) + if options.file is not None: + save_rspec_to_file (value, options.file) + if (self.options.raw is None) and (options.file is None): + print value + + return value + + + def provision(self, options, args): + server = self.sliceapi() + server_version = self.get_cached_server_version(server) + slice_hrn = args[0] + slice_urn = Xrn(slice_hrn, type='slice').get_urn() + + # credentials + creds = [self.slice_credential(slice_hrn)] + delegated_cred = None + if server_version.get('interface') == 'slicemgr': + # delegate our cred to the slice manager + # do not delegate cred to slicemgr...not working at the moment + pass + #if server_version.get('hrn'): + # delegated_cred = self.delegate_cred(slice_cred, server_version['hrn']) + #elif server_version.get('urn'): + # delegated_cred = self.delegate_cred(slice_cred, urn_to_hrn(server_version['urn'])) + + if options.show_credential: + show_credentials(creds) + + api_options = {} + api_options ['call_id'] = unique_call_id() + + # set the requtested rspec version + version_manager = VersionManager() + rspec_version = version_manager._get_version('geni', '3.0').to_dict() + api_options['geni_rspec_version'] = rspec_version + + # users + # need to pass along user keys to the aggregate. + # users = [ + # { urn: urn:publicid:IDN+emulab.net+user+alice + # keys: [, ] + # }] + users = [] + slice_records = self.registry().Resolve(slice_urn, [self.my_credential_string]) + if slice_records and 'researcher' in slice_records[0] and slice_records[0]['researcher']!=[]: + slice_record = slice_records[0] + user_hrns = slice_record['researcher'] + user_urns = [hrn_to_urn(hrn, 'user') for hrn in user_hrns] + user_records = self.registry().Resolve(user_urns, [self.my_credential_string]) + users = pg_users_arg(user_records) + + api_options['geni_users'] = users + result = server.Provision([slice_urn], creds, api_options) + value = ReturnValue.get_value(result) + if self.options.raw: + save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) + if options.file is not None: + save_rspec_to_file (value, options.file) + if (self.options.raw is None) and (options.file is None): + print value + return value + def status(self, options, args): """ retrieve slice status (SliverStatus) @@ -1212,18 +1298,15 @@ or with an slice hrn, shows currently provisioned resources slice_urn = hrn_to_urn(slice_hrn, 'slice') # creds - slice_cred = self.slice_credential_string(slice_hrn) + slice_cred = self.slice_credential(slice_hrn) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} api_options['call_id']=unique_call_id() if options.show_credential: show_credentials(creds) - result = server.SliverStatus(slice_urn, creds, *self.ois(server,api_options)) + result = server.Status([slice_urn], creds, *self.ois(server,api_options)) value = ReturnValue.get_value(result) if self.options.raw: save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) @@ -1243,9 +1326,6 @@ or with an slice hrn, shows currently provisioned resources # cred slice_cred = self.slice_credential_string(args[0]) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # xxx Thierry - does this not need an api_options as well ? result = server.Start(slice_urn, creds) value = ReturnValue.get_value(result) @@ -1266,9 +1346,6 @@ or with an slice hrn, shows currently provisioned resources # cred slice_cred = self.slice_credential_string(args[0]) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) result = server.Stop(slice_urn, creds) value = ReturnValue.get_value(result) if self.options.raw: @@ -1278,21 +1355,24 @@ or with an slice hrn, shows currently provisioned resources return value # reset named slice - def reset(self, options, args): + def action(self, options, args): """ - reset named slice (reset_slice) + Perform the named operational action on the named slivers """ server = self.sliceapi() + api_options = {} # slice urn slice_hrn = args[0] - slice_urn = hrn_to_urn(slice_hrn, 'slice') + action = args[1] + slice_urn = Xrn(slice_hrn, type='slice').get_urn() # cred - slice_cred = self.slice_credential_string(args[0]) + slice_cred = self.slice_credential(args[0]) creds = [slice_cred] if options.delegate: delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) creds.append(delegated_cred) - result = server.reset_slice(creds, slice_urn) + + result = server.PerformOperationalAction([slice_urn], creds, action , api_options) value = ReturnValue.get_value(result) if self.options.raw: save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) @@ -1313,17 +1393,14 @@ or with an slice hrn, shows currently provisioned resources slice_urn = hrn_to_urn(slice_hrn, 'slice') # time: don't try to be smart on the time format, server-side will # creds - slice_cred = self.slice_credential_string(args[0]) + slice_cred = self.slice_credential(args[0]) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} - api_options['call_id']=unique_call_id() + api_options['call_id']=unique_call_id() if options.show_credential: show_credentials(creds) - result = server.RenewSliver(slice_urn, creds, input_time, *self.ois(server,api_options)) + result = server.Renew([slice_urn], creds, input_time, *self.ois(server,api_options)) value = ReturnValue.get_value(result) if self.options.raw: save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) @@ -1341,11 +1418,8 @@ or with an slice hrn, shows currently provisioned resources slice_hrn = args[0] slice_urn = hrn_to_urn(slice_hrn, 'slice') # creds - slice_cred = self.slice_credential_string(slice_hrn) + slice_cred = self.slice_credential(slice_hrn) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) result = server.Shutdown(slice_urn, creds) value = ReturnValue.get_value(result) if self.options.raw: @@ -1366,15 +1440,12 @@ or with an slice hrn, shows currently provisioned resources # creds slice_cred = self.slice_credential_string(slice_hrn) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # rspec rspec_file = self.get_rspec_file(rspec_path) rspec = open(rspec_file).read() # options and call_id when supported api_options = {} - api_options['call_id']=unique_call_id() + api_options['call_id']=unique_call_id() # get ticket at the server ticket_string = server.GetTicket(slice_urn, creds, rspec, *self.ois(server,api_options)) # save @@ -1432,7 +1503,8 @@ or with an slice hrn, shows currently provisioned resources self.print_help() sys.exit(1) target_hrn = args[0] - gid = self.registry().CreateGid(self.my_credential_string, target_hrn, self.client_bootstrap.my_gid_string()) + my_gid_string = open(self.client_bootstrap.my_gid()).read() + gid = self.registry().CreateGid(self.my_credential_string, target_hrn, my_gid_string) if options.file: filename = options.file else: @@ -1441,31 +1513,51 @@ or with an slice hrn, shows currently provisioned resources GID(string=gid).save_to_file(filename) - def delegate(self, options, args): + def delegate (self, options, args): """ (locally) create delegate credential for use by given hrn """ - delegee_hrn = args[0] - if options.delegate_user: - cred = self.delegate_cred(self.my_credential_string, delegee_hrn, 'user') - elif options.delegate_slice: - slice_cred = self.slice_credential_string(options.delegate_slice) - cred = self.delegate_cred(slice_cred, delegee_hrn, 'slice') - else: - self.logger.warning("Must specify either --user or --slice ") - return - delegated_cred = Credential(string=cred) - object_hrn = delegated_cred.get_gid_object().get_hrn() + if len(args) != 1: + self.print_help() + sys.exit(1) + to_hrn = args[0] + # support for several delegations in the same call + # so first we gather the things to do + tuples=[] + for slice_hrn in options.delegate_slices: + message="%s.slice"%slice_hrn + original = self.slice_credential_string(slice_hrn) + tuples.append ( (message, original,) ) + if options.delegate_pi: + my_authority=self.authority + message="%s.pi"%my_authority + original = self.my_authority_credential_string() + tuples.append ( (message, original,) ) + for auth_hrn in options.delegate_auths: + message="%s.auth"%auth_hrn + original=self.authority_credential_string(auth_hrn) + tuples.append ( (message, original, ) ) + # if nothing was specified at all at this point, let's assume -u + if not tuples: options.delegate_user=True + # this user cred if options.delegate_user: - dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_" - + get_leaf(object_hrn) + ".cred") - elif options.delegate_slice: - dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_" - + get_leaf(object_hrn) + ".cred") - - delegated_cred.save_to_file(dest_fn, save_parents=True) - - self.logger.info("delegated credential for %s to %s and wrote to %s"%(object_hrn, delegee_hrn,dest_fn)) + message="%s.user"%self.user + original = self.my_credential_string + tuples.append ( (message, original, ) ) + + # default type for beneficial is user unless -A + if options.delegate_to_authority: to_type='authority' + else: to_type='user' + + # let's now handle all this + # it's all in the filenaming scheme + for (message,original) in tuples: + delegated_string = self.client_bootstrap.delegate_credential_string(original, to_hrn, to_type) + delegated_credential = Credential (string=delegated_string) + filename = os.path.join ( self.options.sfi_dir, + "%s_for_%s.%s.cred"%(message,to_hrn,to_type)) + delegated_credential.save_to_file(filename, save_parents=True) + self.logger.info("delegated credential for %s to %s and wrote to %s"%(message,to_hrn,filename)) def trusted(self, options, args): """