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("-a", "--aggregate", dest="aggregate",
231 default=None, help="aggregate host")
232 parser.add_option("-p", "--port", dest="port",
233 default=AGGREGATE_PORT, help="aggregate port")
234 parser.add_option("-R","--registry-version",
235 action="store_true", dest="version_registry", default=False,
236 help="probe registry version instead of slicemgr")
237 parser.add_option("-l","--local",
238 action="store_true", dest="version_local", default=False,
239 help="display version of the local client")
244 def create_parser(self):
246 # Generate command line parser
247 parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
248 description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
249 parser.add_option("-r", "--registry", dest="registry",
250 help="root registry", metavar="URL", default=None)
251 parser.add_option("-s", "--slicemgr", dest="sm",
252 help="slice manager", metavar="URL", default=None)
253 default_sfi_dir = os.path.expanduser("~/.sfi/")
254 parser.add_option("-d", "--dir", dest="sfi_dir",
255 help="config & working directory - default is " + default_sfi_dir,
256 metavar="PATH", default=default_sfi_dir)
257 parser.add_option("-u", "--user", dest="user",
258 help="user name", metavar="HRN", default=None)
259 parser.add_option("-a", "--auth", dest="auth",
260 help="authority name", metavar="HRN", default=None)
261 parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0,
262 help="verbose mode - cumulative")
263 parser.add_option("-D", "--debug",
264 action="store_true", dest="debug", default=False,
265 help="Debug (xml-rpc) protocol messages")
266 parser.add_option("-p", "--protocol", dest="protocol", default="xmlrpc",
267 help="RPC protocol (xmlrpc or soap)")
268 parser.add_option("-k", "--hashrequest",
269 action="store_true", dest="hashrequest", default=False,
270 help="Create a hash of the request that will be authenticated on the server")
271 parser.disable_interspersed_args()
276 def read_config(self):
277 config_file = self.options.sfi_dir + os.sep + "sfi_config"
279 config = Config (config_file)
281 self.logger.critical("Failed to read configuration file %s"%config_file)
282 self.logger.info("Make sure to remove the export clauses and to add quotes")
283 if self.options.verbose==0:
284 self.logger.info("Re-run with -v for more details")
286 self.logger.log_exc("Could not read config file %s"%config_file)
291 if (self.options.sm is not None):
292 self.sm_url = self.options.sm
293 elif hasattr(config, "SFI_SM"):
294 self.sm_url = config.SFI_SM
296 self.logger.error("You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file)
300 if (self.options.registry is not None):
301 self.reg_url = self.options.registry
302 elif hasattr(config, "SFI_REGISTRY"):
303 self.reg_url = config.SFI_REGISTRY
305 self.logger.errors("You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file)
310 if (self.options.user is not None):
311 self.user = self.options.user
312 elif hasattr(config, "SFI_USER"):
313 self.user = config.SFI_USER
315 self.logger.errors("You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file)
319 if (self.options.auth is not None):
320 self.authority = self.options.auth
321 elif hasattr(config, "SFI_AUTH"):
322 self.authority = config.SFI_AUTH
324 self.logger.error("You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file)
332 # Establish Connection to SliceMgr and Registry Servers
334 def set_servers(self):
337 # Get key and certificate
338 key_file = self.get_key_file()
339 cert_file = self.get_cert_file(key_file)
340 self.key = Keypair(filename=key_file)
341 self.key_file = key_file
342 self.cert_file = cert_file
343 self.cert = Certificate(filename=cert_file)
344 # Establish connection to server(s)
345 self.logger.info("Contacting Registry at: %s"%self.reg_url)
346 self.registry = xmlrpcprotocol.get_server(self.reg_url, key_file, cert_file, self.options)
347 self.logger.info("Contacting Slice Manager at: %s"%self.sm_url)
348 self.slicemgr = xmlrpcprotocol.get_server(self.sm_url, key_file, cert_file, self.options)
353 # Get various credential and spec files
355 # Establishes limiting conventions
356 # - conflates MAs and SAs
357 # - assumes last token in slice name is unique
359 # Bootstraps credentials
360 # - bootstrap user credential from self-signed certificate
361 # - bootstrap authority credential from user credential
362 # - bootstrap slice credential from user credential
366 def get_key_file(self):
367 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
368 if (os.path.isfile(file)):
371 self.logger.error("Key file %s does not exist"%file)
375 def get_cert_file(self, key_file):
377 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
378 if (os.path.isfile(file)):
379 # use existing cert if it exists
383 # attempt to use gid as the cert.
384 gid = self._get_gid()
385 self.logger.info("Writing certificate to %s"%file)
386 gid.save_to_file(file)
388 # generate self signed certificate
389 k = Keypair(filename=key_file)
390 cert = Certificate(subject=self.user)
392 cert.set_issuer(k, self.user)
394 self.logger.info("Writing self-signed certificate to %s"%file)
395 cert.save_to_file(file)
399 def get_cached_gid(self, file):
404 if (os.path.isfile(file)):
405 gid = GID(filename=file)
409 def get_gid(self, opts, args):
411 Get the specify gid and save it to file
416 gid = self._get_gid(hrn)
417 self.logger.debug("Sfi.get_gid-> %s",gid.save_to_string(save_parents=True))
420 def _get_gid(self, hrn=None):
422 git_gid helper. Retrive the gid from the registry and save it to file.
428 gidfile = os.path.join(self.options.sfi_dir, hrn + ".gid")
429 gid = self.get_cached_gid(gidfile)
431 user_cred = self.get_user_cred()
432 records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
434 raise RecordNotFound(args[0])
435 gid = GID(string=records[0]['gid'])
436 self.logger.info("Writing gid to %s"%gidfile)
437 gid.save_to_file(filename=gidfile)
441 def get_cached_credential(self, file):
443 Return a cached credential only if it hasn't expired.
445 if (os.path.isfile(file)):
446 credential = Credential(filename=file)
447 # make sure it isnt expired
448 if not credential.get_expiration or \
449 datetime.datetime.today() < credential.get_expiration():
453 def get_user_cred(self):
454 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
455 return self.get_cred(file, 'user', self.user)
457 def get_auth_cred(self):
458 if not self.authority:
459 self.logger.critical("no authority specified. Use -a or set SF_AUTH")
461 file = os.path.join(self.options.sfi_dir, self.authority + ".cred")
462 return self.get_cred(file, 'authority', self.authority)
464 def get_slice_cred(self, name):
465 file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
466 return self.get_cred(file, 'slice', name)
468 def get_cred(self, file, type, hrn):
469 # attempt to load a cached credential
470 cred = self.get_cached_credential(file)
473 cert_string = self.cert.save_to_string(save_parents=True)
474 user_name = self.user.replace(self.authority + ".", '')
475 if user_name.count(".") > 0:
476 user_name = user_name.replace(".", '_')
477 self.user = self.authority + "." + user_name
478 cred_str = self.registry.GetSelfCredential(cert_string, hrn, "user")
480 # bootstrap slice credential from user credential
481 user_cred = self.get_user_cred().save_to_string(save_parents=True)
482 cred_str = self.registry.GetCredential(user_cred, hrn, type)
485 self.logger.critical("Failed to get %s credential" % type)
488 cred = Credential(string=cred_str)
489 cred.save_to_file(file, save_parents=True)
490 self.logger.info("Writing %s credential to %s" %(type, file))
495 def get_rspec_file(self, rspec):
496 if (os.path.isabs(rspec)):
499 file = os.path.join(self.options.sfi_dir, rspec)
500 if (os.path.isfile(file)):
503 self.logger.critical("No such rspec file %s"%rspec)
506 def get_record_file(self, record):
507 if (os.path.isabs(record)):
510 file = os.path.join(self.options.sfi_dir, record)
511 if (os.path.isfile(file)):
514 self.logger.critical("No such registry record file %s"%record)
517 def load_publickey_string(self, fn):
519 key_string = f.read()
521 # if the filename is a private key file, then extract the public key
522 if "PRIVATE KEY" in key_string:
523 outfn = tempfile.mktemp()
524 cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
527 key_string = f.read()
533 def get_component_server_from_hrn(self, hrn):
534 # direct connection to the nodes component manager interface
535 user_cred = self.get_user_cred().save_to_string(save_parents=True)
536 records = self.registry.Resolve(hrn, user_cred)
537 records = filter_records('node', records)
539 self.logger.warning("No such component:%r"% opts.component)
542 return self.get_server(record['hostname'], CM_PORT, self.key_file, self.cert_file)
544 def get_server(self, host, port, keyfile, certfile):
546 Return an instance of an xmlrpc server connection
548 # port is appended onto the domain, before the path. Should look like:
549 # http://domain:port/path
550 host_parts = host.split('/')
551 host_parts[0] = host_parts[0] + ":" + str(port)
552 url = "http://%s" % "/".join(host_parts)
553 return xmlrpcprotocol.get_server(url, keyfile, certfile, self.options)
555 # xxx opts could be retrieved in self.options
556 def get_server_from_opts(self, opts):
558 Return instance of an xmlrpc connection to a slice manager, aggregate
559 or component server depending on the specified opts
561 server = self.slicemgr
562 # direct connection to an aggregate
563 if hasattr(opts, 'aggregate') and opts.aggregate:
564 server = self.get_server(opts.aggregate, opts.port, self.key_file, self.cert_file)
565 # direct connection to the nodes component manager interface
566 if hasattr(opts, 'component') and opts.component:
567 server = self.get_component_server_from_hrn(opts.component)
570 #==========================================================================
571 # Following functions implement the commands
573 # Registry-related commands
574 #==========================================================================
576 def dispatch(self, command, cmd_opts, cmd_args):
577 return getattr(self, command)(cmd_opts, cmd_args)
579 # list entires in named authority registry
580 def list(self, opts, args):
585 user_cred = self.get_user_cred().save_to_string(save_parents=True)
587 list = self.registry.List(hrn, user_cred)
589 raise Exception, "Not enough parameters for the 'list' command"
591 # filter on person, slice, site, node, etc.
592 # THis really should be in the self.filter_records funct def comment...
593 list = filter_records(opts.type, list)
595 print "%s (%s)" % (record['hrn'], record['type'])
598 if not file.startswith(os.sep):
599 file = os.path.join(self.options.sfi_dir, file)
600 save_records_to_file(file, list)
603 # show named registry record
604 def show(self, opts, args):
609 user_cred = self.get_user_cred().save_to_string(save_parents=True)
610 records = self.registry.Resolve(hrn, user_cred)
611 records = filter_records(opts.type, records)
613 print "No record of type", opts.type
614 for record in records:
615 if record['type'] in ['user']:
616 record = UserRecord(dict=record)
617 elif record['type'] in ['slice']:
618 record = SliceRecord(dict=record)
619 elif record['type'] in ['node']:
620 record = NodeRecord(dict=record)
621 elif record['type'] in ['authority', 'ma', 'sa']:
622 record = AuthorityRecord(dict=record)
624 record = SfaRecord(dict=record)
625 if (opts.format == "text"):
628 print record.save_to_string()
632 if not file.startswith(os.sep):
633 file = os.path.join(self.options.sfi_dir, file)
634 save_records_to_file(file, records)
637 def delegate(self, opts, args):
639 delegee_hrn = args[0]
640 if opts.delegate_user:
641 user_cred = self.get_user_cred()
642 cred = self.delegate_cred(user_cred, delegee_hrn)
643 elif opts.delegate_slice:
644 slice_cred = self.get_slice_cred(opts.delegate_slice)
645 cred = self.delegate_cred(slice_cred, delegee_hrn)
647 self.logger.warning("Must specify either --user or --slice <hrn>")
649 delegated_cred = Credential(string=cred)
650 object_hrn = delegated_cred.get_gid_object().get_hrn()
651 if opts.delegate_user:
652 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
653 + get_leaf(object_hrn) + ".cred")
654 elif opts.delegate_slice:
655 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
656 + get_leaf(object_hrn) + ".cred")
658 delegated_cred.save_to_file(dest_fn, save_parents=True)
660 self.logger.info("delegated credential for %s to %s and wrote to %s"%(object_hrn, delegee_hrn,dest_fn))
662 def delegate_cred(self, object_cred, hrn):
663 # the gid and hrn of the object we are delegating
664 if isinstance(object_cred, str):
665 object_cred = Credential(string=object_cred)
666 object_gid = object_cred.get_gid_object()
667 object_hrn = object_gid.get_hrn()
669 if not object_cred.get_privileges().get_all_delegate():
670 self.logger.error("Object credential %s does not have delegate bit set"%object_hrn)
673 # the delegating user's gid
674 caller_gid = self._get_gid(self.user)
675 caller_gidfile = os.path.join(self.options.sfi_dir, self.user + ".gid")
677 # the gid of the user who will be delegated to
678 delegee_gid = self._get_gid(hrn)
679 delegee_hrn = delegee_gid.get_hrn()
680 delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
681 delegee_gid.save_to_file(filename=delegee_gidfile)
682 dcred = object_cred.delegate(delegee_gidfile, self.get_key_file(), caller_gidfile)
683 return dcred.save_to_string(save_parents=True)
685 # removed named registry record
686 # - have to first retrieve the record to be removed
687 def remove(self, opts, args):
688 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
696 return self.registry.Remove(hrn, auth_cred, type)
698 # add named registry record
699 def add(self, opts, args):
700 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
704 record_filepath = args[0]
705 rec_file = self.get_record_file(record_filepath)
706 record = load_record_from_file(rec_file).as_dict()
707 return self.registry.Register(record, auth_cred)
709 # update named registry entry
710 def update(self, opts, args):
711 user_cred = self.get_user_cred()
715 rec_file = self.get_record_file(args[0])
716 record = load_record_from_file(rec_file)
717 if record['type'] == "user":
718 if record.get_name() == user_cred.get_gid_object().get_hrn():
719 cred = user_cred.save_to_string(save_parents=True)
721 cred = self.get_auth_cred().save_to_string(save_parents=True)
722 elif record['type'] in ["slice"]:
724 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
725 except xmlrpcprotocol.ServerException, e:
726 # XXX smbaker -- once we have better error return codes, update this
727 # to do something better than a string compare
728 if "Permission error" in e.args[0]:
729 cred = self.get_auth_cred().save_to_string(save_parents=True)
732 elif record.get_type() in ["authority"]:
733 cred = self.get_auth_cred().save_to_string(save_parents=True)
734 elif record.get_type() == 'node':
735 cred = self.get_auth_cred().save_to_string(save_parents=True)
737 raise "unknown record type" + record.get_type()
738 record = record.as_dict()
739 return self.registry.Update(record, cred)
741 def get_trusted_certs(self, opts, args):
743 return uhe trusted certs at this interface
745 trusted_certs = self.registry.get_trusted_certs()
746 for trusted_cert in trusted_certs:
747 cert = Certificate(string=trusted_cert)
748 self.logger.debug('Sfi.get_trusted_certs -> %r'%cert.get_subject())
751 def aggregates(self, opts, args):
753 return a list of details about known aggregates
755 user_cred = self.get_user_cred().save_to_string(save_parents=True)
760 result = self.registry.get_aggregates(user_cred, hrn)
764 def registries(self, opts, args):
766 return a list of details about known registries
768 user_cred = self.get_user_cred().save_to_string(save_parents=True)
772 result = self.registry.get_registries(user_cred, hrn)
777 # ==================================================================
778 # Slice-related commands
779 # ==================================================================
782 def version(self, opts, args):
783 if opts.version_local:
784 version=version_core()
786 if opts.version_registry:
789 server = self.get_server_from_opts(opts)
790 version=server.GetVersion()
791 for (k,v) in version.iteritems():
792 print "%-20s: %s"%(k,v)
794 # list instantiated slices
795 def slices(self, opts, args):
797 list instantiated slices
799 user_cred = self.get_user_cred().save_to_string(save_parents=True)
802 delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority))
803 creds.append(delegated_cred)
804 server = self.get_server_from_opts(opts)
805 #results = server.ListSlices(creds, unique_call_id())
806 results = server.ListSlices(creds)
807 display_list(results)
810 # show rspec for named slice
811 def resources(self, opts, args):
812 user_cred = self.get_user_cred().save_to_string(save_parents=True)
813 server = self.slicemgr
815 server = self.get_server_from_opts(opts)
818 cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
820 call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
827 delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
828 creds.append(delegated_cred)
829 if opts.rspec_version:
830 call_options['rspec_version'] = opts.rspec_version
831 result = server.ListResources(creds, call_options,unique_call_id())
833 if opts.file is None:
834 display_rspec(result, format)
837 if not file.startswith(os.sep):
838 file = os.path.join(self.options.sfi_dir, file)
839 save_rspec_to_file(result, file)
842 # created named slice with given rspec
843 def create(self, opts, args):
845 slice_urn = hrn_to_urn(slice_hrn, 'slice')
846 user_cred = self.get_user_cred()
847 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
850 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
851 creds.append(delegated_cred)
852 rspec_file = self.get_rspec_file(args[1])
853 rspec = open(rspec_file).read()
855 # TODO: need to determine if this request is going to a ProtoGENI aggregate. If so
856 # we need to obtain the keys for all users in the slice
859 # { urn: urn:publicid:IDN+emulab.net+user+alice
860 # keys: [<ssh key A>, <ssh key B>]
863 server = self.get_server_from_opts(opts)
864 result = server.CreateSliver(slice_urn, creds, rspec, users, unique_call_id())
868 # get a ticket for the specified slice
869 def get_ticket(self, opts, args):
870 slice_hrn, rspec_path = args[0], args[1]
871 slice_urn = hrn_to_urn(slice_hrn, 'slice')
872 user_cred = self.get_user_cred()
873 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
876 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
877 creds.append(delegated_cred)
878 rspec_file = self.get_rspec_file(rspec_path)
879 rspec = open(rspec_file).read()
880 server = self.get_server_from_opts(opts)
881 ticket_string = server.GetTicket(slice_urn, creds, rspec, [])
882 file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
883 self.logger.info("writing ticket to %s"%file)
884 ticket = SfaTicket(string=ticket_string)
885 ticket.save_to_file(filename=file, save_parents=True)
887 def redeem_ticket(self, opts, args):
888 ticket_file = args[0]
890 # get slice hrn from the ticket
891 # use this to get the right slice credential
892 ticket = SfaTicket(filename=ticket_file)
894 slice_hrn = ticket.gidObject.get_hrn()
895 slice_urn = hrn_to_urn(slice_hrn, 'slice')
896 #slice_hrn = ticket.attributes['slivers'][0]['hrn']
897 user_cred = self.get_user_cred()
898 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
900 # get a list of node hostnames from the RSpec
901 tree = etree.parse(StringIO(ticket.rspec))
902 root = tree.getroot()
903 hostnames = root.xpath("./network/site/node/hostname/text()")
905 # create an xmlrpc connection to the component manager at each of these
906 # components and gall redeem_ticket
908 for hostname in hostnames:
910 self.logger.info("Calling redeem_ticket at %(hostname)s " % locals())
911 server = self.get_server(hostname, CM_PORT, self.key_file, \
912 self.cert_file, self.options.debug)
913 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
914 self.logger.info("Success")
915 except socket.gaierror:
916 self.logger.error("redeem_ticket failed: Component Manager not accepting requests")
918 self.logger.log_exc(e.message)
922 def delete(self, opts, args):
924 slice_urn = hrn_to_urn(slice_hrn, 'slice')
925 slice_cred = self.get_slice_cred(slice_hrn).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.DeleteSliver(slice_urn, creds, unique_call_id())
934 def start(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.Start(slice_urn, creds)
946 def stop(self, opts, args):
948 slice_urn = hrn_to_urn(slice_hrn, 'slice')
949 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
952 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
953 creds.append(delegated_cred)
954 server = self.get_server_from_opts(opts)
955 return server.Stop(slice_urn, creds)
958 def reset(self, opts, args):
960 slice_urn = hrn_to_urn(slice_hrn, 'slice')
961 server = self.get_server_from_opts(opts)
962 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
965 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
966 creds.append(delegated_cred)
967 return server.reset_slice(creds, slice_urn)
969 def renew(self, opts, args):
971 slice_urn = hrn_to_urn(slice_hrn, 'slice')
972 server = self.get_server_from_opts(opts)
973 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
976 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
977 creds.append(delegated_cred)
979 return server.RenewSliver(slice_urn, creds, time, unique_call_id())
982 def status(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 print server.SliverStatus(slice_urn, creds, unique_call_id())
994 def shutdown(self, opts, args):
996 slice_urn = hrn_to_urn(slice_hrn, 'slice')
997 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
1000 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1001 creds.append(delegated_cred)
1002 server = self.get_server_from_opts(opts)
1003 return server.Shutdown(slice_urn, creds)
1005 def print_help (self):
1006 self.sfi_parser.print_help()
1007 self.cmd_parser.print_help()
1010 # Main: parse arguments and dispatch to command
1013 self.sfi_parser = self.create_parser()
1014 (options, args) = self.sfi_parser.parse_args()
1015 self.options = options
1017 self.logger.setLevelFromOptVerbose(self.options.verbose)
1018 if options.hashrequest:
1019 self.hashrequest = True
1022 self.logger.critical("No command given. Use -h for help.")
1026 self.cmd_parser = self.create_cmd_parser(command)
1027 (cmd_opts, cmd_args) = self.cmd_parser.parse_args(args[1:])
1031 self.logger.info("Command=%s" % command)
1032 if command in ("resources"):
1033 self.logger.debug("resources cmd_opts %s" % cmd_opts.format)
1034 elif command in ("list", "show", "remove"):
1035 self.logger.debug("cmd_opts.type %s" % cmd_opts.type)
1036 self.logger.debug('cmd_args %s',cmd_args)
1039 self.dispatch(command, cmd_opts, cmd_args)
1041 self.logger.critical ("Unknown command %s"%command)
1046 if __name__ == "__main__":