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
19 from sfa.util.sfalogging import sfa_logger,sfa_logger_goes_to_console
20 from sfa.trust.certificate import Keypair, Certificate
21 from sfa.trust.gid import GID
22 from sfa.trust.credential import Credential
23 from sfa.util.sfaticket import SfaTicket
24 from sfa.util.record import SfaRecord, UserRecord, SliceRecord, NodeRecord, AuthorityRecord
25 from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn
26 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
27 from sfa.util.config import Config
28 from sfa.util.version import version_core
33 # utility methods here
35 def display_rspec(rspec, format='rspec'):
37 tree = etree.parse(StringIO(rspec))
39 result = root.xpath("./network/site/node/hostname/text()")
40 elif format in ['ip']:
41 # The IP address is not yet part of the new RSpec
42 # so this doesn't do anything yet.
43 tree = etree.parse(StringIO(rspec))
45 result = root.xpath("./network/site/node/ipv4/text()")
52 def display_list(results):
53 for result in results:
56 def display_records(recordList, dump=False):
57 ''' Print all fields in the record'''
58 for record in recordList:
59 display_record(record, dump)
61 def display_record(record, dump=False):
65 info = record.getdict()
66 print "%s (%s)" % (info['hrn'], info['type'])
70 def filter_records(type, records):
72 for record in records:
73 if (record['type'] == type) or (type == "all"):
74 filtered_records.append(record)
75 return filtered_records
79 def save_rspec_to_file(rspec, filename):
80 if not filename.endswith(".rspec"):
81 filename = filename + ".rspec"
83 f = open(filename, 'w')
88 def save_records_to_file(filename, recordList):
90 for record in recordList:
92 save_record_to_file(filename + "." + str(index), record)
94 save_record_to_file(filename, record)
97 def save_record_to_file(filename, record):
98 if record['type'] in ['user']:
99 record = UserRecord(dict=record)
100 elif record['type'] in ['slice']:
101 record = SliceRecord(dict=record)
102 elif record['type'] in ['node']:
103 record = NodeRecord(dict=record)
104 elif record['type'] in ['authority', 'ma', 'sa']:
105 record = AuthorityRecord(dict=record)
107 record = SfaRecord(dict=record)
108 str = record.save_to_string()
109 file(filename, "w").write(str)
114 def load_record_from_file(filename):
115 str = file(filename, "r").read()
116 record = SfaRecord(string=str)
121 def unique_call_id(): return uuid.uuid4().urn
125 required_options=['verbose', 'debug', 'registry', 'sm', 'auth', 'user']
127 # dummy to meet Sfi's expectations for its 'options' field
128 # i.e. s/t we can do setattr on
132 def __init__ (self,options=None):
133 if options is None: options=Sfi.DummyOptions()
134 for opt in Sfi.required_options:
135 if not hasattr(options,opt): setattr(options,opt,None)
136 if not hasattr(options,'sfi_dir'): options.sfi_dir=os.path.expanduser("~/.sfi/")
137 self.options = options
141 self.authority = None
142 self.hashrequest = False
143 sfa_logger_goes_to_console()
144 self.logger=sfa_logger()
146 def create_cmd_parser(self, command, additional_cmdargs=None):
147 cmdargs = {"list": "authority",
152 "aggregates": "[name]",
153 "registries": "[name]",
155 "get_trusted_certs": "cred",
157 "resources": "[name]",
158 "create": "name rspec",
159 "get_ticket": "name rspec",
160 "redeem_ticket": "ticket",
172 if additional_cmdargs:
173 cmdargs.update(additional_cmdargs)
175 if command not in cmdargs:
176 msg="Invalid command\n"
178 msg += ','.join(cmdargs.keys())
179 self.logger.critical(msg)
182 parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
183 % (command, cmdargs[command]))
185 # user specifies remote aggregate/sm/component
186 if command in ("resources", "slices", "create", "delete", "start", "stop",
187 "restart", "shutdown", "get_ticket", "renew", "status"):
188 parser.add_option("-a", "--aggregate", dest="aggregate",
189 default=None, help="aggregate host")
190 parser.add_option("-p", "--port", dest="port",
191 default=AGGREGATE_PORT, help="aggregate port")
192 parser.add_option("-c", "--component", dest="component", default=None,
193 help="component hrn")
194 parser.add_option("-d", "--delegate", dest="delegate", default=None,
196 help="Include a credential delegated to the user's root"+\
197 "authority in set of credentials for this call")
199 # registy filter option
200 if command in ("list", "show", "remove"):
201 parser.add_option("-t", "--type", dest="type", type="choice",
202 help="type filter ([all]|user|slice|authority|node|aggregate)",
203 choices=("all", "user", "slice", "authority", "node", "aggregate"),
206 if command in ("resources"):
207 parser.add_option("-r", "--rspec-version", dest="rspec_version", default="sfa 1",
208 help="schema type and version of resulting RSpec")
209 parser.add_option("-f", "--format", dest="format", type="choice",
210 help="display format ([xml]|dns|ip)", default="xml",
211 choices=("xml", "dns", "ip"))
213 if command in ("resources", "show", "list"):
214 parser.add_option("-o", "--output", dest="file",
215 help="output XML to file", metavar="FILE", default=None)
217 if command in ("show", "list"):
218 parser.add_option("-f", "--format", dest="format", type="choice",
219 help="display format ([text]|xml)", default="text",
220 choices=("text", "xml"))
222 if command in ("delegate"):
223 parser.add_option("-u", "--user",
224 action="store_true", dest="delegate_user", default=False,
225 help="delegate user credential")
226 parser.add_option("-s", "--slice", dest="delegate_slice",
227 help="delegate slice credential", metavar="HRN", default=None)
229 if command in ("version"):
230 parser.add_option("-R","--registry-version",
231 action="store_true", dest="version_registry", default=False,
232 help="probe registry version instead of slicemgr")
233 parser.add_option("-l","--local",
234 action="store_true", dest="version_local", default=False,
235 help="display version of the local client")
240 def create_parser(self):
242 # Generate command line parser
243 parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
244 description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
245 parser.add_option("-r", "--registry", dest="registry",
246 help="root registry", metavar="URL", default=None)
247 parser.add_option("-s", "--slicemgr", dest="sm",
248 help="slice manager", metavar="URL", default=None)
249 default_sfi_dir = os.path.expanduser("~/.sfi/")
250 parser.add_option("-d", "--dir", dest="sfi_dir",
251 help="config & working directory - default is " + default_sfi_dir,
252 metavar="PATH", default=default_sfi_dir)
253 parser.add_option("-u", "--user", dest="user",
254 help="user name", metavar="HRN", default=None)
255 parser.add_option("-a", "--auth", dest="auth",
256 help="authority name", metavar="HRN", default=None)
257 parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0,
258 help="verbose mode - cumulative")
259 parser.add_option("-D", "--debug",
260 action="store_true", dest="debug", default=False,
261 help="Debug (xml-rpc) protocol messages")
262 parser.add_option("-p", "--protocol", dest="protocol", default="xmlrpc",
263 help="RPC protocol (xmlrpc or soap)")
264 parser.add_option("-k", "--hashrequest",
265 action="store_true", dest="hashrequest", default=False,
266 help="Create a hash of the request that will be authenticated on the server")
267 parser.disable_interspersed_args()
272 def read_config(self):
273 config_file = self.options.sfi_dir + os.sep + "sfi_config"
275 config = Config (config_file)
277 self.logger.critical("Failed to read configuration file %s"%config_file)
278 self.logger.info("Make sure to remove the export clauses and to add quotes")
279 if self.options.verbose==0:
280 self.logger.info("Re-run with -v for more details")
282 self.logger.log_exc("Could not read config file %s"%config_file)
287 if (self.options.sm is not None):
288 self.sm_url = self.options.sm
289 elif hasattr(config, "SFI_SM"):
290 self.sm_url = config.SFI_SM
292 self.logger.error("You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file)
296 if (self.options.registry is not None):
297 self.reg_url = self.options.registry
298 elif hasattr(config, "SFI_REGISTRY"):
299 self.reg_url = config.SFI_REGISTRY
301 self.logger.errors("You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file)
306 if (self.options.user is not None):
307 self.user = self.options.user
308 elif hasattr(config, "SFI_USER"):
309 self.user = config.SFI_USER
311 self.logger.errors("You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file)
315 if (self.options.auth is not None):
316 self.authority = self.options.auth
317 elif hasattr(config, "SFI_AUTH"):
318 self.authority = config.SFI_AUTH
320 self.logger.error("You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file)
328 # Establish Connection to SliceMgr and Registry Servers
330 def set_servers(self):
333 # Get key and certificate
334 key_file = self.get_key_file()
335 cert_file = self.get_cert_file(key_file)
336 self.key = Keypair(filename=key_file)
337 self.key_file = key_file
338 self.cert_file = cert_file
339 self.cert = Certificate(filename=cert_file)
340 # Establish connection to server(s)
341 self.logger.info("Contacting Registry at: %s"%self.reg_url)
342 self.registry = xmlrpcprotocol.get_server(self.reg_url, key_file, cert_file, self.options)
343 self.logger.info("Contacting Slice Manager at: %s"%self.sm_url)
344 self.slicemgr = xmlrpcprotocol.get_server(self.sm_url, key_file, cert_file, self.options)
349 # Get various credential and spec files
351 # Establishes limiting conventions
352 # - conflates MAs and SAs
353 # - assumes last token in slice name is unique
355 # Bootstraps credentials
356 # - bootstrap user credential from self-signed certificate
357 # - bootstrap authority credential from user credential
358 # - bootstrap slice credential from user credential
362 def get_key_file(self):
363 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
364 if (os.path.isfile(file)):
367 self.logger.error("Key file %s does not exist"%file)
371 def get_cert_file(self, key_file):
373 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
374 if (os.path.isfile(file)):
375 # use existing cert if it exists
379 # attempt to use gid as the cert.
380 gid = self._get_gid()
381 self.logger.info("Writing certificate to %s"%file)
382 gid.save_to_file(file)
384 # generate self signed certificate
385 k = Keypair(filename=key_file)
386 cert = Certificate(subject=self.user)
388 cert.set_issuer(k, self.user)
390 self.logger.info("Writing self-signed certificate to %s"%file)
391 cert.save_to_file(file)
395 def get_cached_gid(self, file):
400 if (os.path.isfile(file)):
401 gid = GID(filename=file)
405 def get_gid(self, opts, args):
407 Get the specify gid and save it to file
412 gid = self._get_gid(hrn)
413 self.logger.debug("Sfi.get_gid-> %s",gid.save_to_string(save_parents=True))
416 def _get_gid(self, hrn=None):
418 git_gid helper. Retrive the gid from the registry and save it to file.
424 gidfile = os.path.join(self.options.sfi_dir, hrn + ".gid")
425 gid = self.get_cached_gid(gidfile)
427 user_cred = self.get_user_cred()
428 records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
430 raise RecordNotFound(args[0])
431 gid = GID(string=records[0]['gid'])
432 self.logger.info("Writing gid to %s"%gidfile)
433 gid.save_to_file(filename=gidfile)
437 def get_cached_credential(self, file):
439 Return a cached credential only if it hasn't expired.
441 if (os.path.isfile(file)):
442 credential = Credential(filename=file)
443 # make sure it isnt expired
444 if not credential.get_expiration or \
445 datetime.datetime.today() < credential.get_expiration():
449 def get_user_cred(self):
450 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
451 return self.get_cred(file, 'user', self.user)
453 def get_auth_cred(self):
454 if not self.authority:
455 self.logger.critical("no authority specified. Use -a or set SF_AUTH")
457 file = os.path.join(self.options.sfi_dir, self.authority + ".cred")
458 return self.get_cred(file, 'authority', self.authority)
460 def get_slice_cred(self, name):
461 file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
462 return self.get_cred(file, 'slice', name)
464 def get_cred(self, file, type, hrn):
465 # attempt to load a cached credential
466 cred = self.get_cached_credential(file)
469 cert_string = self.cert.save_to_string(save_parents=True)
470 user_name = self.user.replace(self.authority + ".", '')
471 if user_name.count(".") > 0:
472 user_name = user_name.replace(".", '_')
473 self.user = self.authority + "." + user_name
474 cred_str = self.registry.GetSelfCredential(cert_string, hrn, "user")
476 # bootstrap slice credential from user credential
477 user_cred = self.get_user_cred().save_to_string(save_parents=True)
478 cred_str = self.registry.GetCredential(user_cred, hrn, type)
481 self.logger.critical("Failed to get %s credential" % type)
484 cred = Credential(string=cred_str)
485 cred.save_to_file(file, save_parents=True)
486 self.logger.info("Writing %s credential to %s" %(type, file))
491 def get_rspec_file(self, rspec):
492 if (os.path.isabs(rspec)):
495 file = os.path.join(self.options.sfi_dir, rspec)
496 if (os.path.isfile(file)):
499 self.logger.critical("No such rspec file %s"%rspec)
502 def get_record_file(self, record):
503 if (os.path.isabs(record)):
506 file = os.path.join(self.options.sfi_dir, record)
507 if (os.path.isfile(file)):
510 self.logger.critical("No such registry record file %s"%record)
513 def load_publickey_string(self, fn):
515 key_string = f.read()
517 # if the filename is a private key file, then extract the public key
518 if "PRIVATE KEY" in key_string:
519 outfn = tempfile.mktemp()
520 cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
523 key_string = f.read()
529 def get_component_server_from_hrn(self, hrn):
530 # direct connection to the nodes component manager interface
531 user_cred = self.get_user_cred().save_to_string(save_parents=True)
532 records = self.registry.Resolve(hrn, user_cred)
533 records = filter_records('node', records)
535 self.logger.warning("No such component:%r"% opts.component)
538 return self.get_server(record['hostname'], CM_PORT, self.key_file, self.cert_file)
540 def get_server(self, host, port, keyfile, certfile):
542 Return an instance of an xmlrpc server connection
544 # port is appended onto the domain, before the path. Should look like:
545 # http://domain:port/path
546 host_parts = host.split('/')
547 host_parts[0] = host_parts[0] + ":" + str(port)
548 url = "http://%s" % "/".join(host_parts)
549 return xmlrpcprotocol.get_server(url, keyfile, certfile, self.options)
551 # xxx opts could be retrieved in self.options
552 def get_server_from_opts(self, opts):
554 Return instance of an xmlrpc connection to a slice manager, aggregate
555 or component server depending on the specified opts
557 server = self.slicemgr
558 # direct connection to an aggregate
559 if hasattr(opts, 'aggregate') and opts.aggregate:
560 server = self.get_server(opts.aggregate, opts.port, self.key_file, self.cert_file)
561 # direct connection to the nodes component manager interface
562 if hasattr(opts, 'component') and opts.component:
563 server = self.get_component_server_from_hrn(opts.component)
566 #==========================================================================
567 # Following functions implement the commands
569 # Registry-related commands
570 #==========================================================================
572 def dispatch(self, command, cmd_opts, cmd_args):
573 return getattr(self, command)(cmd_opts, cmd_args)
575 # list entires in named authority registry
576 def list(self, opts, args):
581 user_cred = self.get_user_cred().save_to_string(save_parents=True)
583 list = self.registry.List(hrn, user_cred)
585 raise Exception, "Not enough parameters for the 'list' command"
587 # filter on person, slice, site, node, etc.
588 # THis really should be in the self.filter_records funct def comment...
589 list = filter_records(opts.type, list)
591 print "%s (%s)" % (record['hrn'], record['type'])
594 if not file.startswith(os.sep):
595 file = os.path.join(self.options.sfi_dir, file)
596 save_records_to_file(file, list)
599 # show named registry record
600 def show(self, opts, args):
605 user_cred = self.get_user_cred().save_to_string(save_parents=True)
606 records = self.registry.Resolve(hrn, user_cred)
607 records = filter_records(opts.type, records)
609 print "No record of type", opts.type
610 for record in records:
611 if record['type'] in ['user']:
612 record = UserRecord(dict=record)
613 elif record['type'] in ['slice']:
614 record = SliceRecord(dict=record)
615 elif record['type'] in ['node']:
616 record = NodeRecord(dict=record)
617 elif record['type'] in ['authority', 'ma', 'sa']:
618 record = AuthorityRecord(dict=record)
620 record = SfaRecord(dict=record)
621 if (opts.format == "text"):
624 print record.save_to_string()
628 if not file.startswith(os.sep):
629 file = os.path.join(self.options.sfi_dir, file)
630 save_records_to_file(file, records)
633 def delegate(self, opts, args):
635 delegee_hrn = args[0]
636 if opts.delegate_user:
637 user_cred = self.get_user_cred()
638 cred = self.delegate_cred(user_cred, delegee_hrn)
639 elif opts.delegate_slice:
640 slice_cred = self.get_slice_cred(opts.delegate_slice)
641 cred = self.delegate_cred(slice_cred, delegee_hrn)
643 self.logger.warning("Must specify either --user or --slice <hrn>")
645 delegated_cred = Credential(string=cred)
646 object_hrn = delegated_cred.get_gid_object().get_hrn()
647 if opts.delegate_user:
648 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
649 + get_leaf(object_hrn) + ".cred")
650 elif opts.delegate_slice:
651 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
652 + get_leaf(object_hrn) + ".cred")
654 delegated_cred.save_to_file(dest_fn, save_parents=True)
656 self.logger.info("delegated credential for %s to %s and wrote to %s"%(object_hrn, delegee_hrn,dest_fn))
658 def delegate_cred(self, object_cred, hrn):
659 # the gid and hrn of the object we are delegating
660 if isinstance(object_cred, str):
661 object_cred = Credential(string=object_cred)
662 object_gid = object_cred.get_gid_object()
663 object_hrn = object_gid.get_hrn()
665 if not object_cred.get_privileges().get_all_delegate():
666 self.logger.error("Object credential %s does not have delegate bit set"%object_hrn)
669 # the delegating user's gid
670 caller_gid = self._get_gid(self.user)
671 caller_gidfile = os.path.join(self.options.sfi_dir, self.user + ".gid")
673 # the gid of the user who will be delegated to
674 delegee_gid = self._get_gid(hrn)
675 delegee_hrn = delegee_gid.get_hrn()
676 delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
677 delegee_gid.save_to_file(filename=delegee_gidfile)
678 dcred = object_cred.delegate(delegee_gidfile, self.get_key_file(), caller_gidfile)
679 return dcred.save_to_string(save_parents=True)
681 # removed named registry record
682 # - have to first retrieve the record to be removed
683 def remove(self, opts, args):
684 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
692 return self.registry.Remove(hrn, auth_cred, type)
694 # add named registry record
695 def add(self, opts, args):
696 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
700 record_filepath = args[0]
701 rec_file = self.get_record_file(record_filepath)
702 record = load_record_from_file(rec_file).as_dict()
703 return self.registry.Register(record, auth_cred)
705 # update named registry entry
706 def update(self, opts, args):
707 user_cred = self.get_user_cred()
711 rec_file = self.get_record_file(args[0])
712 record = load_record_from_file(rec_file)
713 if record['type'] == "user":
714 if record.get_name() == user_cred.get_gid_object().get_hrn():
715 cred = user_cred.save_to_string(save_parents=True)
717 cred = self.get_auth_cred().save_to_string(save_parents=True)
718 elif record['type'] in ["slice"]:
720 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
721 except xmlrpcprotocol.ServerException, e:
722 # XXX smbaker -- once we have better error return codes, update this
723 # to do something better than a string compare
724 if "Permission error" in e.args[0]:
725 cred = self.get_auth_cred().save_to_string(save_parents=True)
728 elif record.get_type() in ["authority"]:
729 cred = self.get_auth_cred().save_to_string(save_parents=True)
730 elif record.get_type() == 'node':
731 cred = self.get_auth_cred().save_to_string(save_parents=True)
733 raise "unknown record type" + record.get_type()
734 record = record.as_dict()
735 return self.registry.Update(record, cred)
737 def get_trusted_certs(self, opts, args):
739 return uhe trusted certs at this interface
741 trusted_certs = self.registry.get_trusted_certs()
742 for trusted_cert in trusted_certs:
743 cert = Certificate(string=trusted_cert)
744 self.logger.debug('Sfi.get_trusted_certs -> %r'%cert.get_subject())
747 def aggregates(self, opts, args):
749 return a list of details about known aggregates
751 user_cred = self.get_user_cred().save_to_string(save_parents=True)
756 result = self.registry.get_aggregates(user_cred, hrn)
760 def registries(self, opts, args):
762 return a list of details about known registries
764 user_cred = self.get_user_cred().save_to_string(save_parents=True)
768 result = self.registry.get_registries(user_cred, hrn)
773 # ==================================================================
774 # Slice-related commands
775 # ==================================================================
778 def version(self, opts, args):
779 if opts.version_local:
780 version=version_core()
782 if opts.version_registry:
785 server = self.get_server_from_opts(opts)
786 version=server.GetVersion()
787 for (k,v) in version.iteritems():
788 print "%-20s: %s"%(k,v)
790 # list instantiated slices
791 def slices(self, opts, args):
793 list instantiated slices
795 user_cred = self.get_user_cred().save_to_string(save_parents=True)
798 delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority))
799 creds.append(delegated_cred)
800 server = self.get_server_from_opts(opts)
801 #results = server.ListSlices(creds, unique_call_id())
802 results = server.ListSlices(creds)
803 display_list(results)
806 # show rspec for named slice
807 def resources(self, opts, args):
808 user_cred = self.get_user_cred().save_to_string(save_parents=True)
809 server = self.slicemgr
811 server = self.get_server_from_opts(opts)
814 cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
816 call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
823 delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
824 creds.append(delegated_cred)
825 if opts.rspec_version:
826 call_options['rspec_version'] = opts.rspec_version
827 #result = server.ListResources(creds, call_options,unique_call_id())
828 result = server.ListResources(creds, call_options)
830 if opts.file is None:
831 display_rspec(result, format)
834 if not file.startswith(os.sep):
835 file = os.path.join(self.options.sfi_dir, file)
836 save_rspec_to_file(result, file)
839 # created named slice with given rspec
840 def create(self, opts, args):
842 slice_urn = hrn_to_urn(slice_hrn, 'slice')
843 user_cred = self.get_user_cred()
844 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
847 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
848 creds.append(delegated_cred)
849 rspec_file = self.get_rspec_file(args[1])
850 rspec = open(rspec_file).read()
851 server = self.get_server_from_opts(opts)
852 result = server.CreateSliver(slice_urn, creds, rspec, [], unique_call_id())
856 # get a ticket for the specified slice
857 def get_ticket(self, opts, args):
858 slice_hrn, rspec_path = args[0], args[1]
859 slice_urn = hrn_to_urn(slice_hrn, 'slice')
860 user_cred = self.get_user_cred()
861 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
864 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
865 creds.append(delegated_cred)
866 rspec_file = self.get_rspec_file(rspec_path)
867 rspec = open(rspec_file).read()
868 server = self.get_server_from_opts(opts)
869 ticket_string = server.GetTicket(slice_urn, creds, rspec, [])
870 file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
871 self.logger.info("writing ticket to %s"%file)
872 ticket = SfaTicket(string=ticket_string)
873 ticket.save_to_file(filename=file, save_parents=True)
875 def redeem_ticket(self, opts, args):
876 ticket_file = args[0]
878 # get slice hrn from the ticket
879 # use this to get the right slice credential
880 ticket = SfaTicket(filename=ticket_file)
882 slice_hrn = ticket.gidObject.get_hrn()
883 slice_urn = hrn_to_urn(slice_hrn, 'slice')
884 #slice_hrn = ticket.attributes['slivers'][0]['hrn']
885 user_cred = self.get_user_cred()
886 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
888 # get a list of node hostnames from the RSpec
889 tree = etree.parse(StringIO(ticket.rspec))
890 root = tree.getroot()
891 hostnames = root.xpath("./network/site/node/hostname/text()")
893 # create an xmlrpc connection to the component manager at each of these
894 # components and gall redeem_ticket
896 for hostname in hostnames:
898 self.logger.info("Calling redeem_ticket at %(hostname)s " % locals())
899 server = self.get_server(hostname, CM_PORT, self.key_file, \
900 self.cert_file, self.options.debug)
901 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
902 self.logger.info("Success")
903 except socket.gaierror:
904 self.logger.error("redeem_ticket failed: Component Manager not accepting requests")
906 self.logger.log_exc(e.message)
910 def delete(self, opts, args):
912 slice_urn = hrn_to_urn(slice_hrn, 'slice')
913 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
916 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
917 creds.append(delegated_cred)
918 server = self.get_server_from_opts(opts)
919 return server.DeleteSliver(slice_urn, creds, unique_call_id())
922 def start(self, opts, args):
924 slice_urn = hrn_to_urn(slice_hrn, 'slice')
925 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
928 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
929 creds.append(delegated_cred)
930 server = self.get_server_from_opts(opts)
931 return server.Start(slice_urn, creds)
934 def stop(self, opts, args):
936 slice_urn = hrn_to_urn(slice_hrn, 'slice')
937 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
940 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
941 creds.append(delegated_cred)
942 server = self.get_server_from_opts(opts)
943 return server.Stop(slice_urn, creds)
946 def reset(self, opts, args):
948 slice_urn = hrn_to_urn(slice_hrn, 'slice')
949 server = self.get_server_from_opts(opts)
950 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
953 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
954 creds.append(delegated_cred)
955 return server.reset_slice(creds, slice_urn)
957 def renew(self, opts, args):
959 slice_urn = hrn_to_urn(slice_hrn, 'slice')
960 server = self.get_server_from_opts(opts)
961 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
964 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
965 creds.append(delegated_cred)
967 return server.RenewSliver(slice_urn, creds, time, unique_call_id())
970 def status(self, opts, args):
972 slice_urn = hrn_to_urn(slice_hrn, 'slice')
973 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
976 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
977 creds.append(delegated_cred)
978 server = self.get_server_from_opts(opts)
979 print server.SliverStatus(slice_urn, creds, unique_call_id())
982 def shutdown(self, opts, args):
984 slice_urn = hrn_to_urn(slice_hrn, 'slice')
985 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
988 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
989 creds.append(delegated_cred)
990 server = self.get_server_from_opts(opts)
991 return server.Shutdown(slice_urn, creds)
993 def print_help (self):
994 self.sfi_parser.print_help()
995 self.cmd_parser.print_help()
998 # Main: parse arguments and dispatch to command
1001 self.sfi_parser = self.create_parser()
1002 (options, args) = self.sfi_parser.parse_args()
1003 self.options = options
1005 self.logger.setLevelFromOptVerbose(self.options.verbose)
1006 if options.hashrequest:
1007 self.hashrequest = True
1010 self.logger.critical("No command given. Use -h for help.")
1014 self.cmd_parser = self.create_cmd_parser(command)
1015 (cmd_opts, cmd_args) = self.cmd_parser.parse_args(args[1:])
1019 self.logger.info("Command=%s" % command)
1020 if command in ("resources"):
1021 self.logger.debug("resources cmd_opts %s" % cmd_opts.format)
1022 elif command in ("list", "show", "remove"):
1023 self.logger.debug("cmd_opts.type %s" % cmd_opts.type)
1024 self.logger.debug('cmd_args %s',cmd_args)
1027 self.dispatch(command, cmd_opts, cmd_args)
1029 self.logger.critical ("Unknown command %s"%command)
1034 if __name__ == "__main__":