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(hrn, user_cred)
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(hrn, user_cred)
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(hrn, user_cred)
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(args[0], user_cred.save_to_string(save_parents=True))
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 dcred = object_cred.delegate(delegee_gid, self.get_key_file())
574 if opts.delegate_user:
575 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
576 + get_leaf(object_hrn) + ".cred")
577 elif opts.delegate_slice:
578 dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
579 + get_leaf(object_hrn) + ".cred")
581 dcred.save_to_file(dest_fn, save_parents=True)
583 print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
585 # removed named registry record
586 # - have to first retrieve the record to be removed
587 def remove(self, opts, args):
588 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
593 return self.registry.Remove(hrn, auth_cred, type)
595 # add named registry record
596 def add(self, opts, args):
597 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
598 record_filepath = args[0]
599 rec_file = self.get_record_file(record_filepath)
600 record = load_record_from_file(rec_file).as_dict()
601 return self.registry.Register(record, auth_cred)
603 # update named registry entry
604 def update(self, opts, args):
605 user_cred = self.get_user_cred()
606 rec_file = self.get_record_file(args[0])
607 record = load_record_from_file(rec_file)
608 if record['type'] == "user":
609 if record.get_name() == user_cred.get_gid_object().get_hrn():
610 cred = user_cred.save_to_string(save_parents=True)
612 cred = self.get_auth_cred().save_to_string(save_parents=True)
613 elif record['type'] in ["slice"]:
615 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
616 except ServerException, e:
617 # XXX smbaker -- once we have better error return codes, update this
618 # to do something better than a string compare
619 if "Permission error" in e.args[0]:
620 cred = self.get_auth_cred().save_to_string(save_parents=True)
623 elif record.get_type() in ["authority"]:
624 cred = self.get_auth_cred().save_to_string(save_parents=True)
625 elif record.get_type() == 'node':
626 cred = self.get_auth_cred().save_to_string(save_parents=True)
628 raise "unknown record type" + record.get_type()
629 record = record.as_dict()
630 return self.registry.Update(record, cred)
632 def get_trusted_certs(self, opts, args):
634 return uhe trusted certs at this interface
636 trusted_certs = self.registry.get_trusted_certs()
637 for trusted_cert in trusted_certs:
638 cert = Certificate(string=trusted_cert)
639 print cert.get_subject()
642 def aggregates(self, opts, args):
644 return a list of details about known aggregates
646 user_cred = self.get_user_cred().save_to_string(save_parents=True)
651 result = self.registry.get_aggregates(user_cred, hrn)
655 def registries(self, opts, args):
657 return a list of details about known registries
659 user_cred = self.get_user_cred().save_to_string(save_parents=True)
663 result = self.registry.get_registries(user_cred, hrn)
668 # ==================================================================
669 # Slice-related commands
670 # ==================================================================
673 def version(self, opts, args):
674 server = self.get_server_from_opts(opts)
676 print server.GetVersion()
678 # list instantiated slices
679 def slices(self, opts, args):
681 list instantiated slices
683 user_cred = self.get_user_cred().save_to_string(save_parents=True)
684 server = self.get_server_from_opts(opts)
685 results = server.ListSlices([user_cred])
686 display_list(results)
689 # show rspec for named slice
690 def resources(self, opts, args):
691 user_cred = self.get_user_cred().save_to_string(save_parents=True)
692 server = self.slicemgr
694 server = self.get_server_from_opts(opts)
697 cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
699 call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
704 result = server.ListResources([cred], call_options)
706 display_rspec(result, format)
707 if (opts.file is not None):
709 if not file.startswith(os.sep):
710 file = os.path.join(self.options.sfi_dir, file)
711 save_rspec_to_file(result, file)
714 # created named slice with given rspec
715 def create(self, opts, args):
717 slice_urn = hrn_to_urn(slice_hrn, 'slice')
718 user_cred = self.get_user_cred()
719 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
720 rspec_file = self.get_rspec_file(args[1])
721 rspec = open(rspec_file).read()
722 server = self.get_server_from_opts(opts)
723 result = server.CreateSliver(slice_urn, [slice_cred], rspec, [])
727 # get a ticket for the specified slice
728 def get_ticket(self, opts, args):
729 slice_hrn, rspec_path = args[0], args[1]
730 slice_urn = hrn_to_urn(slice_hrn, 'slice')
731 user_cred = self.get_user_cred()
732 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
733 rspec_file = self.get_rspec_file(rspec_path)
734 rspec = open(rspec_file).read()
735 server = self.get_server_from_opts(opts)
736 ticket_string = server.GetTicket(slice_urn, [slice_cred], rspec, [])
737 file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
738 print "writing ticket to ", file
739 ticket = SfaTicket(string=ticket_string)
740 ticket.save_to_file(filename=file, save_parents=True)
742 def redeem_ticket(self, opts, args):
743 ticket_file = args[0]
745 # get slice hrn from the ticket
746 # use this to get the right slice credential
747 ticket = SfaTicket(filename=ticket_file)
749 slice_hrn = ticket.gidObject.get_hrn()
750 slice_urn = hrn_to_urn(slice_hrn, 'slice')
751 #slice_hrn = ticket.attributes['slivers'][0]['hrn']
752 user_cred = self.get_user_cred()
753 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
755 # get a list of node hostnames from the RSpec
756 tree = etree.parse(StringIO(ticket.rspec))
757 root = tree.getroot()
758 hostnames = root.xpath("./network/site/node/hostname/text()")
760 # create an xmlrpc connection to the component manager at each of these
761 # components and gall redeem_ticket
763 for hostname in hostnames:
765 print "Calling redeem_ticket at %(hostname)s " % locals(),
766 server = self.get_server(hostname, CM_PORT, self.key_file, \
767 self.cert_file, self.options.debug)
768 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
770 except socket.gaierror:
772 print "Componet Manager not accepting requests"
774 print "Failed:", e.message
778 def delete(self, opts, args):
780 slice_urn = hrn_to_urn(slice_hrn, 'slice')
781 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
782 server = self.get_server_from_opts(opts)
783 return server.DeleteSliver(slice_urn, [slice_cred])
786 def start(self, opts, args):
788 slice_urn = hrn_to_urn(slice_hrn, 'slice')
789 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
790 server = self.get_server_from_opts(opts)
791 return server.Start(slice_urn, [slice_cred])
794 def stop(self, opts, args):
796 slice_urn = hrn_to_urn(slice_hrn, 'slice')
797 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
798 server = self.get_server_from_opts(opts)
799 return server.Stop(slice_urn, [slice_cred])
802 def reset(self, opts, args):
804 slice_urn = hrn_to_urn(slice_hrn, 'slice')
805 server = self.get_server_from_opts(opts)
806 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
807 return server.reset_slice(slice_cred, slice_urn)
809 def renew(self, opts, args):
811 slice_urn = hrn_to_urn(slice_hrn, 'slice')
812 server = self.get_server_from_opts(opts)
813 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
815 return server.RenewSliver(slice_urn, [slice_cred], time)
818 def status(self, opts, args):
820 slice_urn = hrn_to_urn(slice_hrn, 'slice')
821 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
822 server = self.get_server_from_opts(opts)
823 print server.SliverStatus(slice_urn, [slice_cred])
826 def shutdown(self, opts, args):
828 slice_urn = hrn_to_urn(slice_hrn, 'slice')
829 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
830 server = self.get_server_from_opts(opts)
831 return server.Shutdown(slice_urn, [slice_cred])
834 # Main: parse arguments and dispatch to command
837 parser = self.create_parser()
838 (options, args) = parser.parse_args()
839 self.options = options
841 if options.hashrequest:
842 self.hashrequest = True
845 print "No command given. Use -h for help."
849 (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
850 if self.options.verbose :
851 print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
852 options.sfi_dir, options.user,
854 print "Command %s" % command
855 if command in ("resources"):
856 print "resources cmd_opts %s" % cmd_opts.format
857 elif command in ("list", "show", "remove"):
858 print "cmd_opts.type %s" % cmd_opts.type
859 print "cmd_args %s" % cmd_args
864 self.dispatch(command, cmd_opts, cmd_args)
867 print "Command not found:", command
872 if __name__ == "__main__":