3 # sfi -- slice-based facility interface
13 from lxml import etree
14 from StringIO import StringIO
15 from types import StringTypes, ListType
16 from optparse import OptionParser
17 from sfa.trust.certificate import Keypair, Certificate
18 from sfa.trust.credential import Credential
19 from sfa.util.sfaticket import SfaTicket
20 from sfa.util.record import *
21 from sfa.util.namespace import *
22 from sfa.util.xmlrpcprotocol import ServerException
23 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
24 from sfa.util.config import Config
30 # utility methods here
32 def display_rspec(rspec, format='rspec'):
34 tree = etree.parse(StringIO(rspec))
36 result = root.xpath("./network/site/node/hostname/text()")
37 elif format in ['ip']:
38 # The IP address is not yet part of the new RSpec
39 # so this doesn't do anything yet.
40 tree = etree.parse(StringIO(rspec))
42 result = root.xpath("./network/site/node/ipv4/text()")
49 def display_list(results):
50 for result in results:
53 def display_records(recordList, dump=False):
54 ''' Print all fields in the record'''
55 for record in recordList:
56 display_record(record, dump)
58 def display_record(record, dump=False):
62 info = record.getdict()
63 print "%s (%s)" % (info['hrn'], info['type'])
67 def filter_records(type, records):
69 for record in records:
70 if (record['type'] == type) or (type == "all"):
71 filtered_records.append(record)
72 return filtered_records
76 def save_rspec_to_file(rspec, filename):
77 if not filename.endswith(".rspec"):
78 filename = filename + ".rspec"
80 f = open(filename, 'w')
85 def save_records_to_file(filename, recordList):
87 for record in recordList:
89 save_record_to_file(filename + "." + str(index), record)
91 save_record_to_file(filename, record)
94 def save_record_to_file(filename, record):
95 if record['type'] in ['user']:
96 record = UserRecord(dict=record)
97 elif record['type'] in ['slice']:
98 record = SliceRecord(dict=record)
99 elif record['type'] in ['node']:
100 record = NodeRecord(dict=record)
101 elif record['type'] in ['authority', 'ma', 'sa']:
102 record = AuthorityRecord(dict=record)
104 record = SfaRecord(dict=record)
105 str = record.save_to_string()
106 file(filename, "w").write(str)
111 def load_record_from_file(filename):
112 str = file(filename, "r").read()
113 record = SfaRecord(string=str)
127 def create_cmd_parser(self, command, additional_cmdargs=None):
128 cmdargs = {"list": "name",
133 "aggregates": "[name]",
134 "registries": "[name]",
135 "get_trusted_certs": "cred",
137 "resources": "[name]",
138 "create": "name rspec",
139 "get_ticket": "name rspec",
140 "redeem_ticket": "ticket",
152 if additional_cmdargs:
153 cmdargs.update(additional_cmdargs)
155 if command not in cmdargs:
156 print "Invalid command\n"
158 for key in cmdargs.keys():
163 parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
164 % (command, cmdargs[command]))
166 # user specifies remote aggregate/sm/component
167 if command in ("resources", "slices", "create", "delete", "start", "stop", "restart", "get_ticket", "redeem_ticket"):
168 parser.add_option("-a", "--aggregate", dest="aggregate",
169 default=None, help="aggregate host")
170 parser.add_option("-p", "--port", dest="port",
171 default=AGGREGATE_PORT, help="aggregate port")
172 parser.add_option("-c", "--component", dest="component", default=None,
173 help="component hrn")
175 # registy filter option
176 if command in ("list", "show", "remove"):
177 parser.add_option("-t", "--type", dest="type", type="choice",
178 help="type filter ([all]|user|slice|authority|node|aggregate)",
179 choices=("all", "user", "slice", "authority", "node", "aggregate"),
182 if command in ("resources"):
183 parser.add_option("-f", "--format", dest="format", type="choice",
184 help="display format ([xml]|dns|ip)", default="xml",
185 choices=("xml", "dns", "ip"))
187 if command in ("resources", "show", "list"):
188 parser.add_option("-o", "--output", dest="file",
189 help="output XML to file", metavar="FILE", default=None)
191 if command in ("show", "list"):
192 parser.add_option("-f", "--format", dest="format", type="choice",
193 help="display format ([text]|xml)", default="text",
194 choices=("text", "xml"))
196 if command in ("delegate"):
197 parser.add_option("-u", "--user",
198 action="store_true", dest="delegate_user", default=False,
199 help="delegate user credential")
200 parser.add_option("-s", "--slice", dest="delegate_slice",
201 help="delegate slice credential", metavar="HRN", default=None)
206 def create_parser(self):
208 # Generate command line parser
209 parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
210 description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
211 parser.add_option("-r", "--registry", dest="registry",
212 help="root registry", metavar="URL", default=None)
213 parser.add_option("-s", "--slicemgr", dest="sm",
214 help="slice manager", metavar="URL", default=None)
215 default_sfi_dir = os.path.expanduser("~/.sfi/")
216 parser.add_option("-d", "--dir", dest="sfi_dir",
217 help="config & working directory - default is " + default_sfi_dir,
218 metavar="PATH", default=default_sfi_dir)
219 parser.add_option("-u", "--user", dest="user",
220 help="user name", metavar="HRN", default=None)
221 parser.add_option("-a", "--auth", dest="auth",
222 help="authority name", metavar="HRN", default=None)
223 parser.add_option("-v", "--verbose",
224 action="store_true", dest="verbose", default=False,
226 parser.add_option("-D", "--debug",
227 action="store_true", dest="debug", default=False,
228 help="Debug (xml-rpc) protocol messages")
229 parser.add_option("-p", "--protocol",
230 dest="protocol", default="xmlrpc",
231 help="RPC protocol (xmlrpc or soap)")
232 parser.add_option("-k", "--hashrequest",
233 action="store_true", dest="hashrequest", default=False,
234 help="Create a hash of the request that will be authenticated on the server")
235 parser.disable_interspersed_args()
241 # Establish Connection to SliceMgr and Registry Servers
243 def set_servers(self):
244 config_file = self.options.sfi_dir + os.sep + "sfi_config"
246 config = Config (config_file)
248 print "Failed to read configuration file", config_file
249 print "Make sure to remove the export clauses and to add quotes"
250 if not self.options.verbose:
251 print "Re-run with -v for more details"
253 traceback.print_exc()
258 if (self.options.sm is not None):
259 sm_url = self.options.sm
260 elif hasattr(config, "SFI_SM"):
261 sm_url = config.SFI_SM
263 print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file
267 if (self.options.registry is not None):
268 reg_url = self.options.registry
269 elif hasattr(config, "SFI_REGISTRY"):
270 reg_url = config.SFI_REGISTRY
272 print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file
277 if (self.options.user is not None):
278 self.user = self.options.user
279 elif hasattr(config, "SFI_USER"):
280 self.user = config.SFI_USER
282 print "You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file
286 if (self.options.auth is not None):
287 self.authority = self.options.auth
288 elif hasattr(config, "SFI_AUTH"):
289 self.authority = config.SFI_AUTH
291 print "You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file
297 if self.options.verbose :
298 print "Contacting Slice Manager at:", sm_url
299 print "Contacting Registry at:", reg_url
301 # Get key and certificate
302 key_file = self.get_key_file()
303 cert_file = self.get_cert_file(key_file)
304 self.key = Keypair(filename=key_file)
305 self.key_file = key_file
306 self.cert_file = cert_file
307 self.cert = Certificate(filename=cert_file)
308 # Establish connection to server(s)
309 self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file, self.options.debug)
310 self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file, self.options.debug)
315 # Get various credential and spec files
317 # Establishes limiting conventions
318 # - conflates MAs and SAs
319 # - assumes last token in slice name is unique
321 # Bootstraps credentials
322 # - bootstrap user credential from self-signed certificate
323 # - bootstrap authority credential from user credential
324 # - bootstrap slice credential from user credential
328 def get_key_file(self):
329 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
330 #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
331 if (os.path.isfile(file)):
334 print "Key file", file, "does not exist"
338 def get_cert_file(self, key_file):
340 #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
341 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
342 if (os.path.isfile(file)):
345 k = Keypair(filename=key_file)
346 cert = Certificate(subject=self.user)
348 cert.set_issuer(k, self.user)
350 if self.options.verbose :
351 print "Writing self-signed certificate to", file
352 cert.save_to_file(file)
355 def get_cached_credential(self, file):
357 Return a cached credential only if it hasn't expired.
359 if (os.path.isfile(file)):
360 credential = Credential(filename=file)
361 # make sure it isnt expired
362 if not credential.get_lifetime or \
363 datetime.datetime.today() < credential.get_lifetime():
367 def get_user_cred(self):
368 #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
369 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
370 return self.get_cred(file, 'user', self.user)
372 def get_auth_cred(self):
373 if not self.authority:
374 print "no authority specified. Use -a or set SF_AUTH"
376 file = os.path.join(self.options.sfi_dir, get_leaf("authority") + ".cred")
377 return self.get_cred(file, 'authority', self.authority)
379 def get_slice_cred(self, name):
380 file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
381 return self.get_cred(file, 'slice', name)
383 def get_cred(self, file, type, hrn):
384 # attempt to load a cached credential
385 cred = self.get_cached_credential(file)
388 cert_string = self.cert.save_to_string(save_parents=True)
389 user_name = self.user.replace(self.authority + ".", '')
390 if user_name.count(".") > 0:
391 user_name = user_name.replace(".", '_')
392 self.user = self.authority + "." + user_name
393 cred_str = self.registry.get_self_credential(cert_string, "user", hrn)
395 # bootstrap slice credential from user credential
396 user_cred = self.get_user_cred().save_to_string(save_parents=True)
397 cred_str = self.registry.get_credential(user_cred, type, hrn)
400 print "Failed to get %s credential" % (type)
403 cred = Credential(string=cred_str)
404 cred.save_to_file(file, save_parents=True)
405 if self.options.verbose:
406 print "Writing %s credential to %s" %(type, file)
411 def get_rspec_file(self, rspec):
412 if (os.path.isabs(rspec)):
415 file = os.path.join(self.options.sfi_dir, rspec)
416 if (os.path.isfile(file)):
419 print "No such rspec file", rspec
422 def get_record_file(self, record):
423 if (os.path.isabs(record)):
426 file = os.path.join(self.options.sfi_dir, record)
427 if (os.path.isfile(file)):
430 print "No such registry record file", record
433 def load_publickey_string(self, fn):
435 key_string = f.read()
437 # if the filename is a private key file, then extract the public key
438 if "PRIVATE KEY" in key_string:
439 outfn = tempfile.mktemp()
440 cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
443 key_string = f.read()
448 def get_component_server_from_hrn(self, hrn):
449 # direct connection to the nodes component manager interface
450 user_cred = self.get_user_cred().save_to_string(save_parents=True)
451 records = self.registry.resolve(user_cred, hrn)
452 records = filter_records('node', records)
454 print "No such component:", opts.component
457 return self.get_server(record['hostname'], CM_PORT, self.key_file, \
458 self.cert_file, self.options.debug)
460 def get_server(self, host, port, keyfile, certfile, debug):
462 Return an instnace of an xmlrpc server connection
464 url = "http://%s:%s" % (host, port)
465 return xmlrpcprotocol.get_server(url, keyfile, certfile, debug)
467 def get_server_from_opts(self, opts):
469 Return instance of an xmlrpc connection to a slice manager, aggregate
470 or component server depending on the specified opts
472 server = self.slicemgr
473 # direct connection to an aggregate
474 if hasattr(opts, 'aggregate') and opts.aggregate:
475 server = self.get_server(opts.aggregate, opts.port, self.key_file, \
476 self.cert_file, self.options.debug)
477 # direct connection to the nodes component manager interface
478 if hasattr(opts, 'component') and opts.component:
479 server = self.get_component_server_from_hrn(opts.component)
482 #==========================================================================
483 # Following functions implement the commands
485 # Registry-related commands
486 #==========================================================================
488 def dispatch(self, command, cmd_opts, cmd_args):
489 getattr(self, command)(cmd_opts, cmd_args)
491 # list entires in named authority registry
492 def list(self, opts, args):
493 user_cred = self.get_user_cred().save_to_string(save_parents=True)
496 list = self.registry.list(user_cred, hrn)
498 raise Exception, "Not enough parameters for the 'list' command"
500 # filter on person, slice, site, node, etc.
501 # THis really should be in the self.filter_records funct def comment...
502 list = filter_records(opts.type, list)
504 print "%s (%s)" % (record['hrn'], record['type'])
507 if not file.startswith(os.sep):
508 file = os.path.join(self.options.sfi_dir, file)
509 save_records_to_file(file, list)
512 # show named registry record
513 def show(self, opts, args):
514 user_cred = self.get_user_cred().save_to_string(save_parents=True)
516 records = self.registry.resolve(user_cred, hrn)
517 records = filter_records(opts.type, records)
519 print "No record of type", opts.type
520 for record in records:
521 if record['type'] in ['user']:
522 record = UserRecord(dict=record)
523 elif record['type'] in ['slice']:
524 record = SliceRecord(dict=record)
525 elif record['type'] in ['node']:
526 record = NodeRecord(dict=record)
527 elif record['type'] in ['authority', 'ma', 'sa']:
528 record = AuthorityRecord(dict=record)
530 record = SfaRecord(dict=record)
531 if (opts.format == "text"):
534 print record.save_to_string()
538 if not file.startswith(os.sep):
539 file = os.path.join(self.options.sfi_dir, file)
540 save_records_to_file(file, records)
543 def delegate(self, opts, args):
544 user_cred = self.get_user_cred()
545 if opts.delegate_user:
546 object_cred = user_cred
547 elif opts.delegate_slice:
548 object_cred = self.get_slice_cred(opts.delegate_slice)
550 print "Must specify either --user or --slice <hrn>"
553 # the gid and hrn of the object we are delegating
554 object_gid = object_cred.get_gid_object()
555 object_hrn = object_gid.get_hrn()
557 if not object_cred.get_privileges().get_all_delegate():
558 print "Error: Object credential", object_hrn, "does not have delegate bit set"
561 records = self.registry.resolve(user_cred.save_to_string(save_parents=True), args[0])
562 records = filter_records("user", records)
565 print "Error: Didn't find a user record for", args[0]
568 # the gid of the user who will be delegated to
569 delegee_gid = GID(string=records[0]['gid'])
570 delegee_hrn = delegee_gid.get_hrn()
572 # the key and hrn of the user who will be delegating
573 user_key = Keypair(filename=self.get_key_file())
574 user_hrn = user_cred.get_gid_caller().get_hrn()
575 subject_string = "%s delegated to %s" % (object_hrn, delegee_hrn)
576 dcred = Credential(subject=subject_string)
577 dcred.set_gid_caller(delegee_gid)
578 dcred.set_gid_object(object_gid)
579 privs = object_cred.get_privileges()
580 dcred.set_privileges(object_cred.get_privileges())
581 dcred.get_privileges().delegate_all_privileges(True)
582 dcred.set_pubkey(object_gid.get_pubkey())
583 dcred.set_issuer(user_key, user_hrn)
584 dcred.set_parent(object_cred)
588 if opts.delegate_user:
589 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
590 + get_leaf(object_hrn) + ".cred")
591 elif opts.delegate_slice:
592 dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
593 + get_leaf(object_hrn) + ".cred")
595 dcred.save_to_file(dest_fn, save_parents=True)
597 print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
599 # removed named registry record
600 # - have to first retrieve the record to be removed
601 def remove(self, opts, args):
602 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
607 return self.registry.remove(auth_cred, type, hrn)
609 # add named registry record
610 def add(self, opts, args):
611 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
612 record_filepath = args[0]
613 rec_file = self.get_record_file(record_filepath)
614 record = load_record_from_file(rec_file).as_dict()
615 return self.registry.register(auth_cred, record)
617 # update named registry entry
618 def update(self, opts, args):
619 user_cred = self.get_user_cred()
620 rec_file = self.get_record_file(args[0])
621 record = load_record_from_file(rec_file)
622 if record['type'] == "user":
623 if record.get_name() == user_cred.get_gid_object().get_hrn():
624 cred = user_cred.save_to_string(save_parents=True)
626 cred = self.get_auth_cred().save_to_string(save_parents=True)
627 elif record['type'] in ["slice"]:
629 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
630 except ServerException, e:
631 # XXX smbaker -- once we have better error return codes, update this
632 # to do something better than a string compare
633 if "Permission error" in e.args[0]:
634 cred = self.get_auth_cred().save_to_string(save_parents=True)
637 elif record.get_type() in ["authority"]:
638 cred = self.get_auth_cred().save_to_string(save_parents=True)
639 elif record.get_type() == 'node':
640 cred = self.get_auth_cred().save_to_string(save_parents=True)
642 raise "unknown record type" + record.get_type()
643 record = record.as_dict()
644 return self.registry.update(cred, record)
646 def get_trusted_certs(self, opts, args):
648 return the trusted certs at this interface
650 trusted_certs = self.registry.get_trusted_certs()
651 for trusted_cert in trusted_certs:
652 cert = Certificate(string=trusted_cert)
653 print cert.get_subject()
656 def aggregates(self, opts, args):
658 return a list of details about known aggregates
660 user_cred = self.get_user_cred().save_to_string(save_parents=True)
665 result = self.registry.get_aggregates(user_cred, hrn)
669 def registries(self, opts, args):
671 return a list of details about known registries
673 user_cred = self.get_user_cred().save_to_string(save_parents=True)
677 result = self.registry.get_registries(user_cred, hrn)
682 # ==================================================================
683 # Slice-related commands
684 # ==================================================================
687 def version(self, opts, args):
688 server = self.get_server_from_opts(opts)
690 print server.GetVersion()
692 # list instantiated slices
693 def slices(self, opts, args):
695 list instantiated slices
697 user_cred = self.get_user_cred().save_to_string(save_parents=True)
698 server = self.get_server_from_opts(opts)
699 results = server.ListSlices([user_cred])
700 display_list(results)
703 # show rspec for named slice
704 def resources(self, opts, args):
705 user_cred = self.get_user_cred().save_to_string(save_parents=True)
706 server = self.slicemgr
708 server = self.get_server_from_opts(opts)
711 cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
713 call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
718 result = server.ListResources([cred], call_options)
720 display_rspec(result, format)
721 if (opts.file is not None):
723 if not file.startswith(os.sep):
724 file = os.path.join(self.options.sfi_dir, file)
725 save_rspec_to_file(result, file)
728 # created named slice with given rspec
729 def create(self, opts, args):
731 slice_urn = hrn_to_urn(slice_hrn, 'slice')
732 user_cred = self.get_user_cred()
733 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
734 rspec_file = self.get_rspec_file(args[1])
735 rspec = open(rspec_file).read()
736 server = self.get_server_from_opts(opts)
737 result = server.CreateSliver(slice_urn, [slice_cred], rspec, [])
741 # get a ticket for the specified slice
742 def get_ticket(self, opts, args):
743 slice_hrn, rspec_path = args[0], args[1]
744 slice_urn = hrn_to_urn(slice_hrn, 'slice')
745 user_cred = self.get_user_cred()
746 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
747 rspec_file = self.get_rspec_file(rspec_path)
748 rspec = open(rspec_file).read()
749 server = self.get_server_from_opts(opts)
750 ticket_string = server.GetTicket(slice_urn, [slice_cred], rspec, [])
751 file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
752 print "writing ticket to ", file
753 ticket = SfaTicket(string=ticket_string)
754 ticket.save_to_file(filename=file, save_parents=True)
756 def redeem_ticket(self, opts, args):
757 ticket_file = args[0]
759 # get slice hrn from the ticket
760 # use this to get the right slice credential
761 ticket = SfaTicket(filename=ticket_file)
763 slice_hrn = ticket.gidObject.get_hrn()
764 slice_urn = hrn_to_urn(slice_hrn, 'slice')
765 #slice_hrn = ticket.attributes['slivers'][0]['hrn']
766 user_cred = self.get_user_cred()
767 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
769 # get a list of node hostnames from the RSpec
770 tree = etree.parse(StringIO(ticket.rspec))
771 root = tree.getroot()
772 hostnames = root.xpath("./network/site/node/hostname/text()")
774 # create an xmlrpc connection to the component manager at each of these
775 # components and gall redeem_ticket
777 for hostname in hostnames:
779 print "Calling redeem_ticket at %(hostname)s " % locals(),
780 server = self.get_server(hostname, CM_PORT, self.key_file, \
781 self.cert_file, self.options.debug)
782 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
784 except socket.gaierror:
786 print "Componet Manager not accepting requests"
788 print "Failed:", e.message
792 def delete(self, opts, args):
794 slice_urn = hrn_to_urn(slice_hrn, 'slice')
795 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
796 server = self.get_server_from_opts(opts)
797 return server.DeleteSliver(slice_urn, [slice_cred])
800 def start(self, opts, args):
802 slice_urn = hrn_to_urn(slice_hrn, 'slice')
803 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
804 server = self.get_server_from_opts(opts)
805 return server.Start(slice_urn, [slice_cred])
808 def stop(self, opts, args):
810 slice_urn = hrn_to_urn(slice_hrn, 'slice')
811 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
812 server = self.get_server_from_opts(opts)
813 return server.Stop(slice_urn, [slice_cred])
816 def reset(self, opts, args):
818 slice_urn = hrn_to_urn(slice_hrn, 'slice')
819 server = self.get_server_from_opts(opts)
820 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
821 return server.reset_slice(slice_cred, slice_urn)
823 def renew(self, opts, args):
825 slice_urn = hrn_to_urn(slice_hrn, 'slice')
826 server = self.get_server_from_opts(opts)
827 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
829 return server.RenewSliver(slice_urn, [slice_cred], time)
832 def status(self, opts, args):
834 slice_urn = hrn_to_urn(slice_hrn, 'slice')
835 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
836 server = self.get_server_from_opts(opts)
837 print server.SliverStatus(slice_urn, [slice_cred])
840 def shutdown(self, opts, args):
842 slice_urn = hrn_to_urn(slice_hrn, 'slice')
843 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
844 server = self.get_server_from_opts(opts)
845 return server.Shutdown(slice_urn, [slice_cred])
848 # Main: parse arguments and dispatch to command
851 parser = self.create_parser()
852 (options, args) = parser.parse_args()
853 self.options = options
855 if options.hashrequest:
856 self.hashrequest = True
859 print "No command given. Use -h for help."
863 (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
864 if self.options.verbose :
865 print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
866 options.sfi_dir, options.user,
868 print "Command %s" % command
869 if command in ("resources"):
870 print "resources cmd_opts %s" % cmd_opts.format
871 elif command in ("list", "show", "remove"):
872 print "cmd_opts.type %s" % cmd_opts.type
873 print "cmd_args %s" % cmd_args
878 self.dispatch(command, cmd_opts, cmd_args)
881 print "Command not found:", command
886 if __name__ == "__main__":