X-Git-Url: http://git.onelab.eu/?p=sfa.git;a=blobdiff_plain;f=sfa%2Fclient%2Fsfi.py;h=53d655b80adca14d36803968c5f086cb715b754f;hp=15c83cd6c8f82af172c49ac74796933d9cdf8d20;hb=1cc8e9613cab8b5b22478de369f259e591c54e6d;hpb=f357d5c677573e29f260f82318c9450119474dce diff --git a/sfa/client/sfi.py b/sfa/client/sfi.py index 15c83cd6..53d655b8 100644 --- a/sfa/client/sfi.py +++ b/sfa/client/sfi.py @@ -85,14 +85,23 @@ def display_record(record, dump=False): return -def credential_printable (credential_string): - credential=Credential(string=credential_string) +def filter_records(type, records): + filtered_records = [] + for record in records: + if (record['type'] == type) or (type == "all"): + filtered_records.append(record) + return filtered_records + + +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): @@ -253,14 +262,14 @@ class Sfi: ("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"), @@ -323,8 +332,16 @@ class Sfi: 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", "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 @@ -336,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") @@ -358,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) @@ -619,6 +636,9 @@ use this if you mean an authority instead""") # 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 @@ -635,6 +655,32 @@ use this if you mean an authority instead""") 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 + if isinstance(object_cred, str): + object_cred = Credential(string=object_cred) + object_gid = object_cred.get_gid_object() + object_hrn = object_gid.get_hrn() + + if not object_cred.get_privileges().get_all_delegate(): + self.logger.error("Object credential %s does not have delegate bit set"%object_hrn) + return + + # the delegating user's gid + caller_gidfile = self.my_gid() + + # the gid of the user who will be delegated to + delegee_gid = self.client_bootstrap.gid(hrn,type) + delegee_hrn = delegee_gid.get_hrn() + dcred = object_cred.delegate(delegee_gid, self.private_key, caller_gidfile) + return dcred.save_to_string(save_parents=True) + # # Management of the servers # @@ -943,7 +989,7 @@ or version information about sfi itself creds = [self.my_credential_string] # 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)) @@ -957,19 +1003,15 @@ 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: - the_credential=self.slice_credential_string(args[0]) - creds.append(the_credential) - else: - the_credential=self.my_credential_string - creds.append(the_credential) + creds = [self.my_credential] + if options.delegate: + creds.append(self.delegate_cred(cred, get_authority(self.authority))) if options.show_credential: show_credentials(creds) @@ -980,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: @@ -1013,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 @@ -1074,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() @@ -1101,7 +1177,7 @@ 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] # options and call_id when supported @@ -1109,14 +1185,108 @@ or with an slice hrn, shows currently provisioned resources 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) @@ -1128,7 +1298,7 @@ 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] # options and call_id when supported @@ -1136,7 +1306,7 @@ or with an slice hrn, shows currently provisioned resources 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) @@ -1185,18 +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] - result = server.reset_slice(creds, slice_urn) + if options.delegate: + delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) + creds.append(delegated_cred) + + 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) @@ -1217,14 +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] # 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) @@ -1242,7 +1418,7 @@ 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] result = server.Shutdown(slice_urn, creds) value = ReturnValue.get_value(result) @@ -1269,7 +1445,7 @@ or with an slice hrn, shows currently provisioned resources 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