("remove", "name"),
("resources", ""),
("describe", "slice_hrn"),
- ("create", "slice_hrn rspec"),
("allocate", "slice_hrn rspec"),
("provision", "slice_hrn"),
("action", "slice_hrn action"),
("status", "slice_hrn"),
("renew", "slice_hrn time"),
("shutdown", "slice_hrn"),
- ("get_ticket", "slice_hrn rspec"),
- ("redeem_ticket", "ticket"),
("delegate", "to_hrn"),
+ ("myslice", ""),
("gid", "[name]"),
("trusted", "cred"),
("config", ""),
]
+ examples = {
+ 'myslice' : """
+$ less +/myslice myslice sfi_config
+[myslice]
+backend = 'http://manifold.pl.sophia.inria.fr:7080'
+delegate = 'ple.upmc.slicebrowser'
+user = 'thierry'
+
+$ sfi myslice
+ Will make sure all your credentials are up-to-date (that is: refresh expired ones)
+ then compute delegated credentials for user 'ple.upmc.slicebrowser'
+ and upload them all on myslice backend, using manifold id as specified in 'user'
+"""
+ }
def print_command_help (self, options):
verbose=getattr(options,'verbose')
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"):
+ if command in ("resources", "describe", "allocate", "provision", "delete", "allocate", "provision",
+ "action", "shutdown", "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", "describe", "provision", "allocate", "create","add","update","remove","slices","delete","status","renew"):
+ if command in ("list","resources", "describe", "provision", "allocate", "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
choices=("all", "resources", "leases"), default="resources")
- # 'create' does return the new rspec, makes sense to save that too
- if command in ("resources", "describe", "allocate", "provision", "show", "list", "gid", 'create'):
+ if command in ("resources", "describe", "allocate", "provision", "show", "list", "gid"):
parser.add_option("-o", "--output", dest="file",
help="output XML to file", metavar="FILE", default=None)
self.sfi_parser.print_help()
print "==================== Specific command usage"
self.command_parser.print_help()
+ if self.command in Sfi.examples:
+ print "==================== Example"
+ print Sfi.examples[self.command]
#
# Main: parse arguments and dispatch to command
#
def dispatch(self, command, command_options, command_args):
- method=getattr(self, command,None)
+ method=getattr(self, command, None)
if not method:
print "Unknown command %s"%command
return
self.print_command_help(options)
sys.exit(1)
# second pass options parsing
+ self.command=command
self.command_parser = self.create_command_parser(command)
(command_options, command_args) = self.command_parser.parse_args(args[1:])
self.command_options = command_options
self.read_config ()
self.bootstrap ()
- self.logger.debug("Command=%s" % command)
+ self.logger.debug("Command=%s" % self.command)
try:
self.dispatch(command, command_options, command_args)
+ except SystemExit:
+ return 1
except:
self.logger.log_exc ("sfi command %s failed"%command)
- sys.exit(1)
+ return 1
- return
+ return 0
####################
def read_config(self):
# we need to preload the sections we want parsed
# from the shell config
config.add_section('sfi')
+ # sface users should be able to use this same file to configure their stuff
config.add_section('sface')
+ # manifold users should be able to specify their backend server here for sfi delegate
+ config.add_section('myslice')
config.load(config_file)
# back up old config
shutil.move(config_file, shell_config_file)
# show rspec for named slice
def resources(self, options, args):
"""
- discover available resources
-or with an slice hrn, shows currently provisioned resources
+ discover available resources (ListResources)
"""
server = self.sliceapi()
def describe(self, options, args):
"""
- Shows currently provisioned resources.
+ shows currently allocated/provisioned resources of the named slice or set of slivers (Describe)
"""
server = self.sliceapi()
return
- def create(self, options, args):
- """
- create or update named slice with given rspec
- """
- server = self.sliceapi()
-
- # xxx do we need to check usage (len(args)) ?
- # slice urn
- slice_hrn = args[0]
- slice_urn = hrn_to_urn(slice_hrn, 'slice')
-
- # credentials
- creds = [self.slice_credential_string(slice_hrn)]
-
- delegated_cred = None
- server_version = self.get_cached_server_version(server)
- 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()
-
- # users
- # need to pass along user keys to the aggregate.
- # users = [
- # { urn: urn:publicid:IDN+emulab.net+user+alice
- # keys: [<ssh key A>, <ssh key B>]
- # }]
- users = []
- # 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])
- # 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']
- user_urns = [hrn_to_urn(hrn, 'user') for hrn in user_hrns]
- user_records = self.registry().Resolve(user_urns, [self.my_credential_string])
-
- if 'sfa' not in server_version:
- users = pg_users_arg(user_records)
- rspec = RSpec(rspec)
- rspec.filter({'component_manager_id': server_version['urn']})
- rspec = RSpecConverter.to_pg_rspec(rspec.toxml(), content_type='request')
- else:
- users = sfa_users_arg(user_records, slice_record)
-
- # do not append users, keys, or slice tags. Anything
- # not contained in this request will be removed from the slice
-
- api_options = {}
- api_options ['append'] = False
- api_options ['call_id'] = unique_call_id()
- result = server.CreateSliver(slice_urn, creds, rspec, users, *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)
- 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 delete(self, options, args):
"""
- delete named slice (DeleteSliver)
+ de-allocate and de-provision all or named slivers of the slice (Delete)
"""
server = self.sliceapi()
return value
def allocate(self, options, args):
+ """
+ allocate resources to the named slice (Allocate)
+ """
server = self.sliceapi()
server_version = self.get_cached_server_version(server)
slice_hrn = args[0]
def provision(self, options, args):
+ """
+ provision already allocated resources of named slice (Provision)
+ """
server = self.sliceapi()
server_version = self.get_cached_server_version(server)
slice_hrn = args[0]
def status(self, options, args):
"""
- retrieve slice status (SliverStatus)
+ retrieve the status of the slivers belonging to tne named slice (Status)
"""
server = self.sliceapi()
else:
print value
- def start(self, options, args):
- """
- start named slice (Start)
- """
- server = self.sliceapi()
-
- # the slice urn
- slice_hrn = args[0]
- slice_urn = hrn_to_urn(slice_hrn, 'slice')
-
- # cred
- slice_cred = self.slice_credential_string(args[0])
- creds = [slice_cred]
- # xxx Thierry - does this not need an api_options as well ?
- result = server.Start(slice_urn, creds)
- 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
-
- def stop(self, options, args):
- """
- stop named slice (Stop)
- """
- server = self.sliceapi()
- # slice urn
- slice_hrn = args[0]
- slice_urn = hrn_to_urn(slice_hrn, 'slice')
- # cred
- slice_cred = self.slice_credential_string(args[0])
- creds = [slice_cred]
- result = server.Stop(slice_urn, creds)
- 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
-
# reset named slice
def action(self, options, args):
"""
return value
- def get_ticket(self, options, args):
- """
- get a ticket for the specified slice
- """
- server = self.sliceapi()
- # slice urn
- slice_hrn, rspec_path = args[0], args[1]
- slice_urn = hrn_to_urn(slice_hrn, 'slice')
- # creds
- slice_cred = self.slice_credential_string(slice_hrn)
- creds = [slice_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()
- # get ticket at the server
- ticket_string = server.GetTicket(slice_urn, creds, rspec, *self.ois(server,api_options))
- # save
- file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
- self.logger.info("writing ticket to %s"%file)
- ticket = SfaTicket(string=ticket_string)
- ticket.save_to_file(filename=file, save_parents=True)
-
- def redeem_ticket(self, options, args):
- """
- Connects to nodes in a slice and redeems a ticket
-(slice hrn is retrieved from the ticket)
- """
- ticket_file = args[0]
-
- # get slice hrn from the ticket
- # use this to get the right slice credential
- ticket = SfaTicket(filename=ticket_file)
- ticket.decode()
- ticket_string = ticket.save_to_string(save_parents=True)
-
- slice_hrn = ticket.gidObject.get_hrn()
- slice_urn = hrn_to_urn(slice_hrn, 'slice')
- #slice_hrn = ticket.attributes['slivers'][0]['hrn']
- slice_cred = self.slice_credential_string(slice_hrn)
-
- # get a list of node hostnames from the RSpec
- tree = etree.parse(StringIO(ticket.rspec))
- root = tree.getroot()
- hostnames = root.xpath("./network/site/node/hostname/text()")
-
- # create an xmlrpc connection to the component manager at each of these
- # components and gall redeem_ticket
- connections = {}
- for hostname in hostnames:
- try:
- self.logger.info("Calling redeem_ticket at %(hostname)s " % locals())
- cm_url="http://%s:%s/"%(hostname,CM_PORT)
- server = SfaServerProxy(cm_url, self.private_key, self.my_gid)
- server = self.server_proxy(hostname, CM_PORT, self.private_key,
- timeout=self.options.timeout, verbose=self.options.debug)
- server.RedeemTicket(ticket_string, slice_cred)
- self.logger.info("Success")
- except socket.gaierror:
- self.logger.error("redeem_ticket failed on %s: Component Manager not accepting requests"%hostname)
- except Exception, e:
- self.logger.log_exc(e.message)
- return
-
def gid(self, options, args):
"""
Create a GID (CreateGid)
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 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 that last phase, sfi_config is read to look for the [myslice] section, and
+ namely the 'backend', 'delegate' and 'user' settings"""
+ pass
+
def trusted(self, options, args):
"""
- return uhe trusted certs at this interface (get_trusted_certs)
+ return the trusted certs at this interface (get_trusted_certs)
"""
trusted_certs = self.registry().get_trusted_certs()
for trusted_cert in trusted_certs: