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_gid(self, file):
360 if (os.path.isfile(file)):
361 gid = GID(filename=file)
364 def get_gid(self, hrn):
365 gidfile = os.path.join(self.options.sfi_dir, hrn + ".gid")
366 gid = self.get_cached_gid(gidfile)
368 user_cred = self.get_user_cred()
369 records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
371 raise RecordNotFound(args[0])
372 gid = GID(string=records[0]['gid'])
373 if self.options.verbose:
374 print "Writing gid to ", gidfile
375 gid.save_to_file(filename=gidfile)
379 def get_cached_credential(self, file):
381 Return a cached credential only if it hasn't expired.
383 if (os.path.isfile(file)):
384 credential = Credential(filename=file)
385 # make sure it isnt expired
386 if not credential.get_lifetime or \
387 datetime.datetime.today() < credential.get_lifetime():
391 def get_user_cred(self):
392 #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
393 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
394 return self.get_cred(file, 'user', self.user)
396 def get_auth_cred(self):
397 if not self.authority:
398 print "no authority specified. Use -a or set SF_AUTH"
400 file = os.path.join(self.options.sfi_dir, get_leaf("authority") + ".cred")
401 return self.get_cred(file, 'authority', self.authority)
403 def get_slice_cred(self, name):
404 file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
405 return self.get_cred(file, 'slice', name)
407 def get_cred(self, file, type, hrn):
408 # attempt to load a cached credential
409 cred = self.get_cached_credential(file)
412 cert_string = self.cert.save_to_string(save_parents=True)
413 user_name = self.user.replace(self.authority + ".", '')
414 if user_name.count(".") > 0:
415 user_name = user_name.replace(".", '_')
416 self.user = self.authority + "." + user_name
417 cred_str = self.registry.get_self_credential(cert_string, "user", hrn)
419 # bootstrap slice credential from user credential
420 user_cred = self.get_user_cred().save_to_string(save_parents=True)
421 cred_str = self.registry.get_credential(user_cred, type, hrn)
424 print "Failed to get %s credential" % (type)
427 cred = Credential(string=cred_str)
428 cred.save_to_file(file, save_parents=True)
429 if self.options.verbose:
430 print "Writing %s credential to %s" %(type, file)
435 def get_rspec_file(self, rspec):
436 if (os.path.isabs(rspec)):
439 file = os.path.join(self.options.sfi_dir, rspec)
440 if (os.path.isfile(file)):
443 print "No such rspec file", rspec
446 def get_record_file(self, record):
447 if (os.path.isabs(record)):
450 file = os.path.join(self.options.sfi_dir, record)
451 if (os.path.isfile(file)):
454 print "No such registry record file", record
457 def load_publickey_string(self, fn):
459 key_string = f.read()
461 # if the filename is a private key file, then extract the public key
462 if "PRIVATE KEY" in key_string:
463 outfn = tempfile.mktemp()
464 cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
467 key_string = f.read()
472 def get_component_server_from_hrn(self, hrn):
473 # direct connection to the nodes component manager interface
474 user_cred = self.get_user_cred().save_to_string(save_parents=True)
475 records = self.registry.Resolve(hrn, user_cred)
476 records = filter_records('node', records)
478 print "No such component:", opts.component
481 return self.get_server(record['hostname'], CM_PORT, self.key_file, \
482 self.cert_file, self.options.debug)
484 def get_server(self, host, port, keyfile, certfile, debug):
486 Return an instnace of an xmlrpc server connection
488 url = "http://%s:%s" % (host, port)
489 return xmlrpcprotocol.get_server(url, keyfile, certfile, debug)
491 def get_server_from_opts(self, opts):
493 Return instance of an xmlrpc connection to a slice manager, aggregate
494 or component server depending on the specified opts
496 server = self.slicemgr
497 # direct connection to an aggregate
498 if hasattr(opts, 'aggregate') and opts.aggregate:
499 server = self.get_server(opts.aggregate, opts.port, self.key_file, \
500 self.cert_file, self.options.debug)
501 # direct connection to the nodes component manager interface
502 if hasattr(opts, 'component') and opts.component:
503 server = self.get_component_server_from_hrn(opts.component)
506 #==========================================================================
507 # Following functions implement the commands
509 # Registry-related commands
510 #==========================================================================
512 def dispatch(self, command, cmd_opts, cmd_args):
513 getattr(self, command)(cmd_opts, cmd_args)
515 # list entires in named authority registry
516 def list(self, opts, args):
517 user_cred = self.get_user_cred().save_to_string(save_parents=True)
520 list = self.registry.List(hrn, user_cred)
522 raise Exception, "Not enough parameters for the 'list' command"
524 # filter on person, slice, site, node, etc.
525 # THis really should be in the self.filter_records funct def comment...
526 list = filter_records(opts.type, list)
528 print "%s (%s)" % (record['hrn'], record['type'])
531 if not file.startswith(os.sep):
532 file = os.path.join(self.options.sfi_dir, file)
533 save_records_to_file(file, list)
536 # show named registry record
537 def show(self, opts, args):
538 user_cred = self.get_user_cred().save_to_string(save_parents=True)
540 records = self.registry.Resolve(hrn, user_cred)
541 records = filter_records(opts.type, records)
543 print "No record of type", opts.type
544 for record in records:
545 if record['type'] in ['user']:
546 record = UserRecord(dict=record)
547 elif record['type'] in ['slice']:
548 record = SliceRecord(dict=record)
549 elif record['type'] in ['node']:
550 record = NodeRecord(dict=record)
551 elif record['type'] in ['authority', 'ma', 'sa']:
552 record = AuthorityRecord(dict=record)
554 record = SfaRecord(dict=record)
555 if (opts.format == "text"):
558 print record.save_to_string()
562 if not file.startswith(os.sep):
563 file = os.path.join(self.options.sfi_dir, file)
564 save_records_to_file(file, records)
567 def delegate(self, opts, args):
568 user_cred = self.get_user_cred()
569 if opts.delegate_user:
570 object_cred = user_cred
571 elif opts.delegate_slice:
572 object_cred = self.get_slice_cred(opts.delegate_slice)
574 print "Must specify either --user or --slice <hrn>"
577 # the gid and hrn of the object we are delegating
578 object_gid = object_cred.get_gid_object()
579 object_hrn = object_gid.get_hrn()
581 if not object_cred.get_privileges().get_all_delegate():
582 print "Error: Object credential", object_hrn, "does not have delegate bit set"
585 # the gid of the user who will be delegated to
586 delegee_gid = self.get_gid(args[0])
587 delegee_hrn = delegee_gid.get_hrn()
588 delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
589 delegee_gid.save_to_file(filename=delegee_gidfile)
590 dcred = object_cred.delegate(delegee_gidfile, self.get_key_file())
592 if opts.delegate_user:
593 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
594 + get_leaf(object_hrn) + ".cred")
595 elif opts.delegate_slice:
596 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
597 + get_leaf(object_hrn) + ".cred")
599 dcred.save_to_file(dest_fn, save_parents=True)
601 print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
603 # removed named registry record
604 # - have to first retrieve the record to be removed
605 def remove(self, opts, args):
606 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
611 return self.registry.Remove(hrn, auth_cred, type)
613 # add named registry record
614 def add(self, opts, args):
615 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
616 record_filepath = args[0]
617 rec_file = self.get_record_file(record_filepath)
618 record = load_record_from_file(rec_file).as_dict()
619 return self.registry.Register(record, auth_cred)
621 # update named registry entry
622 def update(self, opts, args):
623 user_cred = self.get_user_cred()
624 rec_file = self.get_record_file(args[0])
625 record = load_record_from_file(rec_file)
626 if record['type'] == "user":
627 if record.get_name() == user_cred.get_gid_object().get_hrn():
628 cred = user_cred.save_to_string(save_parents=True)
630 cred = self.get_auth_cred().save_to_string(save_parents=True)
631 elif record['type'] in ["slice"]:
633 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
634 except ServerException, e:
635 # XXX smbaker -- once we have better error return codes, update this
636 # to do something better than a string compare
637 if "Permission error" in e.args[0]:
638 cred = self.get_auth_cred().save_to_string(save_parents=True)
641 elif record.get_type() in ["authority"]:
642 cred = self.get_auth_cred().save_to_string(save_parents=True)
643 elif record.get_type() == 'node':
644 cred = self.get_auth_cred().save_to_string(save_parents=True)
646 raise "unknown record type" + record.get_type()
647 record = record.as_dict()
648 return self.registry.Update(record, cred)
650 def get_trusted_certs(self, opts, args):
652 return uhe trusted certs at this interface
654 trusted_certs = self.registry.get_trusted_certs()
655 for trusted_cert in trusted_certs:
656 cert = Certificate(string=trusted_cert)
657 print cert.get_subject()
660 def aggregates(self, opts, args):
662 return a list of details about known aggregates
664 user_cred = self.get_user_cred().save_to_string(save_parents=True)
669 result = self.registry.get_aggregates(user_cred, hrn)
673 def registries(self, opts, args):
675 return a list of details about known registries
677 user_cred = self.get_user_cred().save_to_string(save_parents=True)
681 result = self.registry.get_registries(user_cred, hrn)
686 # ==================================================================
687 # Slice-related commands
688 # ==================================================================
691 def version(self, opts, args):
692 server = self.get_server_from_opts(opts)
694 print server.GetVersion()
696 # list instantiated slices
697 def slices(self, opts, args):
699 list instantiated slices
701 user_cred = self.get_user_cred().save_to_string(save_parents=True)
702 server = self.get_server_from_opts(opts)
703 results = server.ListSlices([user_cred])
704 display_list(results)
707 # show rspec for named slice
708 def resources(self, opts, args):
709 user_cred = self.get_user_cred().save_to_string(save_parents=True)
710 server = self.slicemgr
712 server = self.get_server_from_opts(opts)
715 cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
717 call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
722 result = server.ListResources([cred], call_options)
724 display_rspec(result, format)
725 if (opts.file is not None):
727 if not file.startswith(os.sep):
728 file = os.path.join(self.options.sfi_dir, file)
729 save_rspec_to_file(result, file)
732 # created named slice with given rspec
733 def create(self, opts, args):
735 slice_urn = hrn_to_urn(slice_hrn, 'slice')
736 user_cred = self.get_user_cred()
737 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
738 rspec_file = self.get_rspec_file(args[1])
739 rspec = open(rspec_file).read()
740 server = self.get_server_from_opts(opts)
741 result = server.CreateSliver(slice_urn, [slice_cred], rspec, [])
745 # get a ticket for the specified slice
746 def get_ticket(self, opts, args):
747 slice_hrn, rspec_path = args[0], args[1]
748 slice_urn = hrn_to_urn(slice_hrn, 'slice')
749 user_cred = self.get_user_cred()
750 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
751 rspec_file = self.get_rspec_file(rspec_path)
752 rspec = open(rspec_file).read()
753 server = self.get_server_from_opts(opts)
754 ticket_string = server.GetTicket(slice_urn, [slice_cred], rspec, [])
755 file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
756 print "writing ticket to ", file
757 ticket = SfaTicket(string=ticket_string)
758 ticket.save_to_file(filename=file, save_parents=True)
760 def redeem_ticket(self, opts, args):
761 ticket_file = args[0]
763 # get slice hrn from the ticket
764 # use this to get the right slice credential
765 ticket = SfaTicket(filename=ticket_file)
767 slice_hrn = ticket.gidObject.get_hrn()
768 slice_urn = hrn_to_urn(slice_hrn, 'slice')
769 #slice_hrn = ticket.attributes['slivers'][0]['hrn']
770 user_cred = self.get_user_cred()
771 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
773 # get a list of node hostnames from the RSpec
774 tree = etree.parse(StringIO(ticket.rspec))
775 root = tree.getroot()
776 hostnames = root.xpath("./network/site/node/hostname/text()")
778 # create an xmlrpc connection to the component manager at each of these
779 # components and gall redeem_ticket
781 for hostname in hostnames:
783 print "Calling redeem_ticket at %(hostname)s " % locals(),
784 server = self.get_server(hostname, CM_PORT, self.key_file, \
785 self.cert_file, self.options.debug)
786 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
788 except socket.gaierror:
790 print "Componet Manager not accepting requests"
792 print "Failed:", e.message
796 def delete(self, opts, args):
798 slice_urn = hrn_to_urn(slice_hrn, 'slice')
799 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
800 server = self.get_server_from_opts(opts)
801 return server.DeleteSliver(slice_urn, [slice_cred])
804 def start(self, opts, args):
806 slice_urn = hrn_to_urn(slice_hrn, 'slice')
807 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
808 server = self.get_server_from_opts(opts)
809 return server.Start(slice_urn, [slice_cred])
812 def stop(self, opts, args):
814 slice_urn = hrn_to_urn(slice_hrn, 'slice')
815 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
816 server = self.get_server_from_opts(opts)
817 return server.Stop(slice_urn, [slice_cred])
820 def reset(self, opts, args):
822 slice_urn = hrn_to_urn(slice_hrn, 'slice')
823 server = self.get_server_from_opts(opts)
824 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
825 return server.reset_slice(slice_cred, slice_urn)
827 def renew(self, opts, args):
829 slice_urn = hrn_to_urn(slice_hrn, 'slice')
830 server = self.get_server_from_opts(opts)
831 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
833 return server.RenewSliver(slice_urn, [slice_cred], time)
836 def status(self, opts, args):
838 slice_urn = hrn_to_urn(slice_hrn, 'slice')
839 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
840 server = self.get_server_from_opts(opts)
841 print server.SliverStatus(slice_urn, [slice_cred])
844 def shutdown(self, opts, args):
846 slice_urn = hrn_to_urn(slice_hrn, 'slice')
847 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
848 server = self.get_server_from_opts(opts)
849 return server.Shutdown(slice_urn, [slice_cred])
852 # Main: parse arguments and dispatch to command
855 parser = self.create_parser()
856 (options, args) = parser.parse_args()
857 self.options = options
859 if options.hashrequest:
860 self.hashrequest = True
863 print "No command given. Use -h for help."
867 (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
868 if self.options.verbose :
869 print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
870 options.sfi_dir, options.user,
872 print "Command %s" % command
873 if command in ("resources"):
874 print "resources cmd_opts %s" % cmd_opts.format
875 elif command in ("list", "show", "remove"):
876 print "cmd_opts.type %s" % cmd_opts.type
877 print "cmd_args %s" % cmd_args
882 self.dispatch(command, cmd_opts, cmd_args)
885 print "Command not found:", command
890 if __name__ == "__main__":