X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fclient%2Fsfi.py;h=2ce796b01cd10ee435730bc125be0a4da2db95cd;hb=dcec4892ea998e7df5297ba08a7a93da0e8d7053;hp=dca8e9adb362bc3ad757b139f646539a4a4d6bf0;hpb=01aa57aac6c8f4edf68587e94de8eead60452e00;p=sfa.git diff --git a/sfa/client/sfi.py b/sfa/client/sfi.py index dca8e9ad..2ce796b0 100644 --- a/sfa/client/sfi.py +++ b/sfa/client/sfi.py @@ -203,7 +203,7 @@ def load_record_from_opts(options): record_dict['keys'] = [pubkey] if hasattr(options, 'slices') and options.slices: record_dict['slices'] = options.slices - if hasattr(options, 'researchers') and options.researchers: + if hasattr(options, 'researchers') and options.researchers is not None: record_dict['researcher'] = options.researchers if hasattr(options, 'email') and options.email: record_dict['email'] = options.email @@ -241,13 +241,19 @@ from functools import wraps commands_list=[] commands_dict={} -def register_command (args_string, example): +def declare_command (args_string, example,aliases=None): def wrap(m): name=getattr(m,'__name__') doc=getattr(m,'__doc__',"-- missing doc --") doc=doc.strip(" \t\n") commands_list.append(name) - commands_dict[name]=(doc, args_string, example) + # last item is 'canonical' name, so we can know which commands are aliases + command_tuple=(doc, args_string, example,name) + commands_dict[name]=command_tuple + if aliases is not None: + for alias in aliases: + commands_list.append(alias) + commands_dict[alias]=command_tuple @wraps(m) def new_method (*args, **kwds): return m(*args, **kwds) return new_method @@ -292,7 +298,8 @@ class Sfi: ### suitable if no reasonable command has been provided def print_commands_help (self, options): verbose=getattr(options,'verbose') - format3="%18s %-15s %s" + format3="%10s %-30s %s" + format3offset=42 line=80*'-' if not verbose: print format3%("command","cmd_args","description") @@ -302,19 +309,29 @@ class Sfi: self.create_parser_global().print_help() # preserve order from the code for command in commands_list: - (doc, args_string, example) = commands_dict[command] + try: + (doc, args_string, example, canonical) = commands_dict[command] + except: + print "Cannot find info on command %s - skipped"%command + continue if verbose: print line - doc=doc.replace("\n","\n"+35*' ') - print format3%(command,args_string,doc) - if verbose: - self.create_parser_command(command).print_help() + if command==canonical: + doc=doc.replace("\n","\n"+format3offset*' ') + print format3%(command,args_string,doc) + if verbose: + self.create_parser_command(command).print_help() + else: + print format3%(command,"<>"%canonical,"") ### now if a known command was found we can be more verbose on that one def print_help (self): print "==================== Generic sfi usage" self.sfi_parser.print_help() - (doc,_,example)=commands_dict[self.command] + (doc,_,example,canonical)=commands_dict[self.command] + if canonical != self.command: + print "\n==================== NOTE: %s is an alias for genuine %s"%(self.command,canonical) + self.command=canonical print "\n==================== Purpose of %s"%self.command print doc print "\n==================== Specific usage for %s"%self.command @@ -374,7 +391,7 @@ class Sfi: sys.exit(2) # retrieve args_string - (_, args_string, __) = commands_dict[command] + (_, args_string, __,___) = commands_dict[command] parser = OptionParser(add_help_option=False, usage="sfi [sfi_options] %s [cmd_options] %s" @@ -396,7 +413,7 @@ class Sfi: action="store_true", dest="registry_interface", default=False, help="target the registry interface instead of slice interface") - if command in ("add", "update"): + if command in ("register", "update"): 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)") @@ -405,7 +422,7 @@ class Sfi: 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='Set/replace slice researchers', default='', type="str", action='callback', + help='Set/replace slice researchers - use -r none to reset', default='', type="str", action='callback', callback=optparse_listvalue_callback) parser.add_option('-p', '--pis', dest='pis', metavar='', help='Set/replace Principal Investigators/Project Managers', default='', type="str", action='callback', callback=optparse_listvalue_callback) @@ -422,7 +439,7 @@ class Sfi: "authority in set of credentials for this call") # show_credential option - if command in ("list","resources", "describe", "provision", "allocate", "add","update","remove","delete","status","renew"): + if command in ("list","resources", "describe", "provision", "allocate", "register","update","remove","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 @@ -434,6 +451,8 @@ 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") + parser.add_option("-n","--no-details",dest="no_details",action="store_true",default=False, + help="call Resolve without the 'details' option") if command in ("resources", "describe"): # rspec version parser.add_option("-r", "--rspec-version", dest="rspec_version", default="GENI 3", @@ -847,7 +866,7 @@ use this if you mean an authority instead""") # Registry-related commands #========================================================================== - @register_command("","") + @declare_command("","") def config (self, options, args): "Display contents of current config" print "# From configuration file %s"%self.config_file @@ -871,11 +890,11 @@ use this if you mean an authority instead""") value=getattr(self.config_instance,varname) print "%-20s = %s"%(name,value) - @register_command("","") + @declare_command("","") def version(self, options, args): """ display an SFA server version (GetVersion) - or version information about sfi itself + or version information about sfi itself """ if options.version_local: version=version_core() @@ -892,7 +911,7 @@ use this if you mean an authority instead""") pprinter = PrettyPrinter(indent=4) pprinter.pprint(version) - @register_command("authority","") + @declare_command("authority","") def list(self, options, args): """ list entries in named authority registry (List) @@ -920,7 +939,7 @@ use this if you mean an authority instead""") save_records_to_file(options.file, list, options.fileformat) return - @register_command("name","") + @declare_command("name","") def show(self, options, args): """ show details about named registry record (Resolve) @@ -930,7 +949,9 @@ use this if you mean an authority instead""") sys.exit(1) hrn = args[0] # explicitly require Resolve to run in details mode - record_dicts = self.registry().Resolve(hrn, self.my_credential_string, {'details':True}) + resolve_options={} + if not options.no_details: resolve_options['details']=True + record_dicts = self.registry().Resolve(hrn, self.my_credential_string, resolve_options) record_dicts = filter_records(options.type, record_dicts) if not record_dicts: self.logger.error("No record of type %s"% options.type) @@ -952,11 +973,12 @@ use this if you mean an authority instead""") save_records_to_file(options.file, record_dicts, options.fileformat) return - @register_command("[xml-filename]","") - def add(self, options, args): - """add record into registry (Register) - from command line options (recommended) - old-school method involving an xml file still supported""" + # this historically was named 'add', it is now 'register' with an alias for legacy + @declare_command("[xml-filename]","",['add']) + def register(self, options, args): + """create new record in registry (Register) + from command line options (recommended) + old-school method involving an xml file still supported""" auth_cred = self.my_authority_credential_string() if options.show_credential: @@ -988,11 +1010,11 @@ use this if you mean an authority instead""") record_dict['last_name'] = record_dict['hrn'] return self.registry().Register(record_dict, auth_cred) - @register_command("[xml-filename]","") + @declare_command("[xml-filename]","") def update(self, options, args): """update record into registry (Update) - from command line options (recommended) - old-school method involving an xml file still supported""" + from command line options (recommended) + old-school method involving an xml file still supported""" record_dict = {} if len(args) > 0: record_filepath = args[0] @@ -1032,7 +1054,7 @@ use this if you mean an authority instead""") show_credentials(cred) return self.registry().Update(record_dict, cred) - @register_command("hrn","") + @declare_command("hrn","") def remove(self, options, args): "remove registry record by name (Remove)" auth_cred = self.my_authority_credential_string() @@ -1052,7 +1074,7 @@ use this if you mean an authority instead""") # ================================================================== # show rspec for named slice - @register_command("","") + @declare_command("","") def resources(self, options, args): """ discover available resources (ListResources) @@ -1103,11 +1125,11 @@ use this if you mean an authority instead""") return - @register_command("slice_hrn","") + @declare_command("slice_hrn","") def describe(self, options, args): """ shows currently allocated/provisioned resources - of the named slice or set of slivers (Describe) + of the named slice or set of slivers (Describe) """ server = self.sliceapi() @@ -1120,10 +1142,13 @@ use this if you mean an authority instead""") api_options = {'call_id': unique_call_id(), 'cached': True, - 'info': options.info, + #'info': options.info, 'list_leases': options.list_leases, 'geni_rspec_version': {'type': 'geni', 'version': '3'}, } + if options.info: + api_options['info'] = options.info + if options.rspec_version: version_manager = VersionManager() server_version = self.get_cached_server_version(server) @@ -1144,10 +1169,10 @@ use this if you mean an authority instead""") return - @register_command("slice_hrn [ ... ]","") + @declare_command("slice_hrn [...]","") def delete(self, options, args): """ - de-allocate and de-provision all or named slivers of the slice (Delete) + de-allocate and de-provision all or named slivers of the named slice (Delete) """ server = self.sliceapi() @@ -1179,7 +1204,7 @@ use this if you mean an authority instead""") print value return value - @register_command("slice_hrn rspec","") + @declare_command("slice_hrn rspec","") def allocate(self, options, args): """ allocate resources to the named slice (Allocate) @@ -1236,10 +1261,10 @@ use this if you mean an authority instead""") return value - @register_command("slice_hrn [ ... ]","") + @declare_command("slice_hrn [...]","") def provision(self, options, args): """ - provision already or named allocated slivers of the named slice (Provision) + provision all or named already allocated slivers of the named slice (Provision) """ server = self.sliceapi() server_version = self.get_cached_server_version(server) @@ -1301,10 +1326,10 @@ use this if you mean an authority instead""") print value return value - @register_command("slice_hrn","") + @declare_command("slice_hrn","") def status(self, options, args): """ - retrieve the status of the slivers belonging to tne named slice (Status) + retrieve the status of the slivers belonging to the named slice (Status) """ server = self.sliceapi() @@ -1330,10 +1355,10 @@ use this if you mean an authority instead""") # Thierry: seemed to be missing return value - @register_command("slice_hrn [ ... ] action","") + @declare_command("slice_hrn [...] action","") def action(self, options, args): """ - Perform the named operational action on these slivers + Perform the named operational action on all or named slivers of the named slice """ server = self.sliceapi() api_options = {} @@ -1362,18 +1387,26 @@ use this if you mean an authority instead""") print value return value - @register_command("slice_hrn time","") + @declare_command("slice_hrn [...] time","") def renew(self, options, args): """ - renew slice (RenewSliver) + renew slice (Renew) """ server = self.sliceapi() - if len(args) != 2: + if len(args) < 2: self.print_help() sys.exit(1) - [ slice_hrn, input_time ] = args - # slice urn - slice_urn = hrn_to_urn(slice_hrn, 'slice') + slice_hrn = args[0] + slice_urn = Xrn(slice_hrn, type='slice').get_urn() + + if len(args) > 2: + # we have sliver urns + sliver_urns = args[1:-1] + else: + # we provision all the slivers of the slice + sliver_urns = [slice_urn] + input_time = args[-1] + # time: don't try to be smart on the time format, server-side will # creds slice_cred = self.slice_credential(args[0]) @@ -1383,7 +1416,7 @@ use this if you mean an authority instead""") api_options['call_id']=unique_call_id() if options.show_credential: show_credentials(creds) - result = server.Renew([slice_urn], creds, input_time, *self.ois(server,api_options)) + result = server.Renew(sliver_urns, 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) @@ -1392,7 +1425,7 @@ use this if you mean an authority instead""") return value - @register_command("slice_hrn","") + @declare_command("slice_hrn","") def shutdown(self, options, args): """ shutdown named slice (Shutdown) @@ -1413,7 +1446,7 @@ use this if you mean an authority instead""") return value - @register_command("[name]","") + @declare_command("[name]","") def gid(self, options, args): """ Create a GID (CreateGid) @@ -1432,7 +1465,7 @@ use this if you mean an authority instead""") GID(string=gid).save_to_file(filename) #################### - @register_command("to_hrn","""$ sfi delegate -u -p -s ple.inria.heartbeat -s ple.inria.omftest ple.upmc.slicebrowser + @declare_command("to_hrn","""$ sfi delegate -u -p -s ple.inria.heartbeat -s ple.inria.omftest ple.upmc.slicebrowser will locally create a set of delegated credentials for the benefit of ple.upmc.slicebrowser the set of credentials in the scope for this call would be @@ -1448,8 +1481,8 @@ use this if you mean an authority instead""") def delegate (self, options, args): """ (locally) create delegate credential for use by given hrn - make sure to check for 'sfi myslice' instead if you plan - on using MySlice + make sure to check for 'sfi myslice' instead if you plan + on using MySlice """ if len(args) != 1: self.print_help() @@ -1494,7 +1527,7 @@ use this if you mean an authority instead""") self.logger.info("delegated credential for %s to %s and wrote to %s"%(message,to_hrn,filename)) #################### - @register_command("","""$ less +/myslice sfi_config + @declare_command("","""$ less +/myslice sfi_config [myslice] backend = http://manifold.pl.sophia.inria.fr:7080 # the HRN that myslice uses, so that we are delegating to @@ -1518,15 +1551,15 @@ $ sfi m -b http://mymanifold.foo.com:7080/ is synonym to sfi myslice as no other command starts with an 'm' and uses a custom backend for this one call """ -) # register_command +) # declare_command def myslice (self, options, args): """ This helper is for refreshing your credentials at myslice; it will - * compute all the slices that you currently have credentials on - * refresh all your credentials (you as a user and pi, your slices) - * upload them to the manifold backend server - for last phase, sfi_config is read to look for the [myslice] section, - and namely the 'backend', 'delegate' and 'user' settings""" + * compute all the slices that you currently have credentials on + * refresh all your credentials (you as a user and pi, your slices) + * upload them to the manifold backend server + for last phase, sfi_config is read to look for the [myslice] section, + and namely the 'backend', 'delegate' and 'user' settings""" ########## if len(args)>0: @@ -1632,7 +1665,7 @@ $ sfi m -b http://mymanifold.foo.com:7080/ if count_success != count_all: sys.exit(1) return - @register_command("cred","") + @declare_command("cred","") def trusted(self, options, args): """ return the trusted certs at this interface (get_trusted_certs)