3 # sfi -- slice-based facility interface
14 from lxml import etree
15 from StringIO import StringIO
16 from types import StringTypes, ListType
17 from optparse import OptionParser
18 from sfa.util.sfalogging import sfi_logger
19 from sfa.trust.certificate import Keypair, Certificate
20 from sfa.trust.gid import GID
21 from sfa.trust.credential import Credential
22 from sfa.util.sfaticket import SfaTicket
23 from sfa.util.record import SfaRecord, UserRecord, SliceRecord, NodeRecord, AuthorityRecord
24 from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn
25 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
26 from sfa.util.config import Config
27 from sfa.util.version import version_core
28 from sfa.util.cache import Cache
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.sfi_dir = options.sfi_dir
138 self.options = options
142 self.authority = None
143 self.hashrequest = False
144 self.logger = sfi_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"))
212 #panos: a new option to define the type of information about resources a user is interested in
213 parser.add_option("-i", "--info", dest="info",
214 help="optional component information", default=None)
217 if command in ("resources", "show", "list"):
218 parser.add_option("-o", "--output", dest="file",
219 help="output XML to file", metavar="FILE", default=None)
221 if command in ("show", "list"):
222 parser.add_option("-f", "--format", dest="format", type="choice",
223 help="display format ([text]|xml)", default="text",
224 choices=("text", "xml"))
226 if command in ("delegate"):
227 parser.add_option("-u", "--user",
228 action="store_true", dest="delegate_user", default=False,
229 help="delegate user credential")
230 parser.add_option("-s", "--slice", dest="delegate_slice",
231 help="delegate slice credential", metavar="HRN", default=None)
233 if command in ("version"):
234 parser.add_option("-a", "--aggregate", dest="aggregate",
235 default=None, help="aggregate host")
236 parser.add_option("-p", "--port", dest="port",
237 default=AGGREGATE_PORT, help="aggregate port")
238 parser.add_option("-R","--registry-version",
239 action="store_true", dest="version_registry", default=False,
240 help="probe registry version instead of slicemgr")
241 parser.add_option("-l","--local",
242 action="store_true", dest="version_local", default=False,
243 help="display version of the local client")
248 def create_parser(self):
250 # Generate command line parser
251 parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
252 description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
253 parser.add_option("-r", "--registry", dest="registry",
254 help="root registry", metavar="URL", default=None)
255 parser.add_option("-s", "--slicemgr", dest="sm",
256 help="slice manager", metavar="URL", default=None)
257 default_sfi_dir = os.path.expanduser("~/.sfi/")
258 parser.add_option("-d", "--dir", dest="sfi_dir",
259 help="config & working directory - default is " + default_sfi_dir,
260 metavar="PATH", default=default_sfi_dir)
261 parser.add_option("-u", "--user", dest="user",
262 help="user name", metavar="HRN", default=None)
263 parser.add_option("-a", "--auth", dest="auth",
264 help="authority name", metavar="HRN", default=None)
265 parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0,
266 help="verbose mode - cumulative")
267 parser.add_option("-D", "--debug",
268 action="store_true", dest="debug", default=False,
269 help="Debug (xml-rpc) protocol messages")
270 parser.add_option("-p", "--protocol", dest="protocol", default="xmlrpc",
271 help="RPC protocol (xmlrpc or soap)")
272 parser.add_option("-k", "--hashrequest",
273 action="store_true", dest="hashrequest", default=False,
274 help="Create a hash of the request that will be authenticated on the server")
275 parser.disable_interspersed_args()
280 def read_config(self):
281 config_file = self.options.sfi_dir + os.sep + "sfi_config"
283 config = Config (config_file)
285 self.logger.critical("Failed to read configuration file %s"%config_file)
286 self.logger.info("Make sure to remove the export clauses and to add quotes")
287 if self.options.verbose==0:
288 self.logger.info("Re-run with -v for more details")
290 self.logger.log_exc("Could not read config file %s"%config_file)
295 if (self.options.sm is not None):
296 self.sm_url = self.options.sm
297 elif hasattr(config, "SFI_SM"):
298 self.sm_url = config.SFI_SM
300 self.logger.error("You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file)
304 if (self.options.registry is not None):
305 self.reg_url = self.options.registry
306 elif hasattr(config, "SFI_REGISTRY"):
307 self.reg_url = config.SFI_REGISTRY
309 self.logger.errors("You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file)
314 if (self.options.user is not None):
315 self.user = self.options.user
316 elif hasattr(config, "SFI_USER"):
317 self.user = config.SFI_USER
319 self.logger.errors("You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file)
323 if (self.options.auth is not None):
324 self.authority = self.options.auth
325 elif hasattr(config, "SFI_AUTH"):
326 self.authority = config.SFI_AUTH
328 self.logger.error("You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file)
336 # Establish Connection to SliceMgr and Registry Servers
338 def set_servers(self):
341 # Get key and certificate
342 key_file = self.get_key_file()
343 cert_file = self.get_cert_file(key_file)
344 self.key = Keypair(filename=key_file)
345 self.key_file = key_file
346 self.cert_file = cert_file
347 self.cert = GID(filename=cert_file)
348 self.logger.info("Contacting Registry at: %s"%self.reg_url)
349 self.registry = xmlrpcprotocol.get_server(self.reg_url, key_file, cert_file, self.options)
350 self.logger.info("Contacting Slice Manager at: %s"%self.sm_url)
351 self.slicemgr = xmlrpcprotocol.get_server(self.sm_url, key_file, cert_file, self.options)
354 def get_cached_server_version(self, server):
355 # check local cache first
358 cache_file = self.sfi_dir + os.path.sep + 'sfi_cache.dat'
359 cache_key = server.url + "-version"
361 cache = Cache(cache_file)
364 self.logger.info("Local cache not found at: %s" % cache_file)
367 version = cache.get(cache_key)
370 version = server.GetVersion()
371 # cache version for 24 hours
372 cache.add(cache_key, version, ttl= 60*60*24)
373 self.logger.info("Updating cache file %s" % cache_file)
374 cache.save_to_file(cache_file)
380 def server_supports_call_id_arg(self, server):
382 Returns true if server support the optional call_id arg, false otherwise.
384 server_version = self.get_cached_server_version(server)
385 if 'sfa' in server_version:
386 code_tag = server_version['code_tag']
387 code_tag_parts = code_tag.split("-")
389 version_parts = code_tag_parts[0].split(".")
390 major, minor = version_parts[0], version_parts[1]
391 rev = code_tag_parts[1]
393 if int(minor) > 0 or int(rev) > 20:
398 # Get various credential and spec files
400 # Establishes limiting conventions
401 # - conflates MAs and SAs
402 # - assumes last token in slice name is unique
404 # Bootstraps credentials
405 # - bootstrap user credential from self-signed certificate
406 # - bootstrap authority credential from user credential
407 # - bootstrap slice credential from user credential
411 def get_key_file(self):
412 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
413 if (os.path.isfile(file)):
416 self.logger.error("Key file %s does not exist"%file)
420 def get_cert_file(self, key_file):
422 cert_file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
423 if (os.path.isfile(cert_file)):
424 # we'd perfer to use Registry issued certs instead of self signed certs.
425 # if this is a Registry cert (GID) then we are done
426 gid = GID(filename=cert_file)
430 # generate self signed certificate
431 k = Keypair(filename=key_file)
432 cert = Certificate(subject=self.user)
434 cert.set_issuer(k, self.user)
436 self.logger.info("Writing self-signed certificate to %s"%cert_file)
437 cert.save_to_file(cert_file)
439 # try to get registry issued cert
441 self.logger.info("Getting Registry issued cert")
443 # *hack. need to set registyr before _get_gid() is called
444 self.registry = xmlrpcprotocol.get_server(self.reg_url, key_file, cert_file, self.options)
445 gid = self._get_gid(type='user')
447 self.logger.info("Writing certificate to %s"%cert_file)
448 gid.save_to_file(cert_file)
450 self.logger.info("Failed to download Registry issued cert")
454 def get_cached_gid(self, file):
459 if (os.path.isfile(file)):
460 gid = GID(filename=file)
464 def get_gid(self, opts, args):
466 Get the specify gid and save it to file
471 gid = self._get_gid(hrn)
472 self.logger.debug("Sfi.get_gid-> %s",gid.save_to_string(save_parents=True))
475 def _get_gid(self, hrn=None, type=None):
477 git_gid helper. Retrive the gid from the registry and save it to file.
483 gidfile = os.path.join(self.options.sfi_dir, hrn + ".gid")
485 gid = self.get_cached_gid(gidfile)
487 user_cred = self.get_user_cred()
488 records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
490 raise RecordNotFound(args[0])
495 if type == rec['type']:
498 raise RecordNotFound(args[0])
500 gid = GID(string=record['gid'])
501 self.logger.info("Writing gid to %s"%gidfile)
502 gid.save_to_file(filename=gidfile)
506 def get_cached_credential(self, file):
508 Return a cached credential only if it hasn't expired.
510 if (os.path.isfile(file)):
511 credential = Credential(filename=file)
512 # make sure it isnt expired
513 if not credential.get_expiration or \
514 datetime.datetime.today() < credential.get_expiration():
518 def get_user_cred(self):
519 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
520 return self.get_cred(file, 'user', self.user)
522 def get_auth_cred(self):
523 if not self.authority:
524 self.logger.critical("no authority specified. Use -a or set SF_AUTH")
526 file = os.path.join(self.options.sfi_dir, self.authority + ".cred")
527 return self.get_cred(file, 'authority', self.authority)
529 def get_slice_cred(self, name):
530 file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
531 return self.get_cred(file, 'slice', name)
533 def get_cred(self, file, type, hrn):
534 # attempt to load a cached credential
535 cred = self.get_cached_credential(file)
538 cert_string = self.cert.save_to_string(save_parents=True)
539 user_name = self.user.replace(self.authority + ".", '')
540 if user_name.count(".") > 0:
541 user_name = user_name.replace(".", '_')
542 self.user = self.authority + "." + user_name
543 cred_str = self.registry.GetSelfCredential(cert_string, hrn, "user")
545 # bootstrap slice credential from user credential
546 user_cred = self.get_user_cred().save_to_string(save_parents=True)
547 cred_str = self.registry.GetCredential(user_cred, hrn, type)
550 self.logger.critical("Failed to get %s credential" % type)
553 cred = Credential(string=cred_str)
554 cred.save_to_file(file, save_parents=True)
555 self.logger.info("Writing %s credential to %s" %(type, file))
560 def get_rspec_file(self, rspec):
561 if (os.path.isabs(rspec)):
564 file = os.path.join(self.options.sfi_dir, rspec)
565 if (os.path.isfile(file)):
568 self.logger.critical("No such rspec file %s"%rspec)
571 def get_record_file(self, record):
572 if (os.path.isabs(record)):
575 file = os.path.join(self.options.sfi_dir, record)
576 if (os.path.isfile(file)):
579 self.logger.critical("No such registry record file %s"%record)
582 def load_publickey_string(self, fn):
584 key_string = f.read()
586 # if the filename is a private key file, then extract the public key
587 if "PRIVATE KEY" in key_string:
588 outfn = tempfile.mktemp()
589 cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
592 key_string = f.read()
598 def get_component_server_from_hrn(self, hrn):
599 # direct connection to the nodes component manager interface
600 user_cred = self.get_user_cred().save_to_string(save_parents=True)
601 records = self.registry.Resolve(hrn, user_cred)
602 records = filter_records('node', records)
604 self.logger.warning("No such component:%r"% opts.component)
607 return self.get_server(record['hostname'], CM_PORT, self.key_file, self.cert_file)
609 def get_server(self, host, port, keyfile, certfile):
611 Return an instance of an xmlrpc server connection
613 # port is appended onto the domain, before the path. Should look like:
614 # http://domain:port/path
615 host_parts = host.split('/')
616 host_parts[0] = host_parts[0] + ":" + str(port)
617 url = "http://%s" % "/".join(host_parts)
618 return xmlrpcprotocol.get_server(url, keyfile, certfile, self.options)
620 # xxx opts could be retrieved in self.options
621 def get_server_from_opts(self, opts):
623 Return instance of an xmlrpc connection to a slice manager, aggregate
624 or component server depending on the specified opts
626 server = self.slicemgr
627 # direct connection to an aggregate
628 if hasattr(opts, 'aggregate') and opts.aggregate:
629 server = self.get_server(opts.aggregate, opts.port, self.key_file, self.cert_file)
630 # direct connection to the nodes component manager interface
631 if hasattr(opts, 'component') and opts.component:
632 server = self.get_component_server_from_hrn(opts.component)
635 #==========================================================================
636 # Following functions implement the commands
638 # Registry-related commands
639 #==========================================================================
641 def dispatch(self, command, cmd_opts, cmd_args):
642 return getattr(self, command)(cmd_opts, cmd_args)
644 # list entires in named authority registry
645 def list(self, opts, args):
650 user_cred = self.get_user_cred().save_to_string(save_parents=True)
652 list = self.registry.List(hrn, user_cred)
654 raise Exception, "Not enough parameters for the 'list' command"
656 # filter on person, slice, site, node, etc.
657 # THis really should be in the self.filter_records funct def comment...
658 list = filter_records(opts.type, list)
660 print "%s (%s)" % (record['hrn'], record['type'])
663 if not file.startswith(os.sep):
664 file = os.path.join(self.options.sfi_dir, file)
665 save_records_to_file(file, list)
668 # show named registry record
669 def show(self, opts, args):
674 user_cred = self.get_user_cred().save_to_string(save_parents=True)
675 records = self.registry.Resolve(hrn, user_cred)
676 records = filter_records(opts.type, records)
678 print "No record of type", opts.type
679 for record in records:
680 if record['type'] in ['user']:
681 record = UserRecord(dict=record)
682 elif record['type'] in ['slice']:
683 record = SliceRecord(dict=record)
684 elif record['type'] in ['node']:
685 record = NodeRecord(dict=record)
686 elif record['type'].startswith('authority'):
687 record = AuthorityRecord(dict=record)
689 record = SfaRecord(dict=record)
690 if (opts.format == "text"):
693 print record.save_to_string()
697 if not file.startswith(os.sep):
698 file = os.path.join(self.options.sfi_dir, file)
699 save_records_to_file(file, records)
702 def delegate(self, opts, args):
704 delegee_hrn = args[0]
705 if opts.delegate_user:
706 user_cred = self.get_user_cred()
707 cred = self.delegate_cred(user_cred, delegee_hrn)
708 elif opts.delegate_slice:
709 slice_cred = self.get_slice_cred(opts.delegate_slice)
710 cred = self.delegate_cred(slice_cred, delegee_hrn)
712 self.logger.warning("Must specify either --user or --slice <hrn>")
714 delegated_cred = Credential(string=cred)
715 object_hrn = delegated_cred.get_gid_object().get_hrn()
716 if opts.delegate_user:
717 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
718 + get_leaf(object_hrn) + ".cred")
719 elif opts.delegate_slice:
720 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
721 + get_leaf(object_hrn) + ".cred")
723 delegated_cred.save_to_file(dest_fn, save_parents=True)
725 self.logger.info("delegated credential for %s to %s and wrote to %s"%(object_hrn, delegee_hrn,dest_fn))
727 def delegate_cred(self, object_cred, hrn):
728 # the gid and hrn of the object we are delegating
729 if isinstance(object_cred, str):
730 object_cred = Credential(string=object_cred)
731 object_gid = object_cred.get_gid_object()
732 object_hrn = object_gid.get_hrn()
734 if not object_cred.get_privileges().get_all_delegate():
735 self.logger.error("Object credential %s does not have delegate bit set"%object_hrn)
738 # the delegating user's gid
739 caller_gid = self._get_gid(self.user)
740 caller_gidfile = os.path.join(self.options.sfi_dir, self.user + ".gid")
742 # the gid of the user who will be delegated to
743 delegee_gid = self._get_gid(hrn)
744 delegee_hrn = delegee_gid.get_hrn()
745 delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
746 delegee_gid.save_to_file(filename=delegee_gidfile)
747 dcred = object_cred.delegate(delegee_gidfile, self.get_key_file(), caller_gidfile)
748 return dcred.save_to_string(save_parents=True)
750 # removed named registry record
751 # - have to first retrieve the record to be removed
752 def remove(self, opts, args):
753 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
761 return self.registry.Remove(hrn, auth_cred, type)
763 # add named registry record
764 def add(self, opts, args):
765 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
769 record_filepath = args[0]
770 rec_file = self.get_record_file(record_filepath)
771 record = load_record_from_file(rec_file).as_dict()
772 return self.registry.Register(record, auth_cred)
774 # update named registry entry
775 def update(self, opts, args):
776 user_cred = self.get_user_cred()
780 rec_file = self.get_record_file(args[0])
781 record = load_record_from_file(rec_file)
782 if record['type'] == "user":
783 if record.get_name() == user_cred.get_gid_object().get_hrn():
784 cred = user_cred.save_to_string(save_parents=True)
786 cred = self.get_auth_cred().save_to_string(save_parents=True)
787 elif record['type'] in ["slice"]:
789 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
790 except xmlrpcprotocol.ServerException, e:
791 # XXX smbaker -- once we have better error return codes, update this
792 # to do something better than a string compare
793 if "Permission error" in e.args[0]:
794 cred = self.get_auth_cred().save_to_string(save_parents=True)
797 elif record.get_type() in ["authority"]:
798 cred = self.get_auth_cred().save_to_string(save_parents=True)
799 elif record.get_type() == 'node':
800 cred = self.get_auth_cred().save_to_string(save_parents=True)
802 raise "unknown record type" + record.get_type()
803 record = record.as_dict()
804 return self.registry.Update(record, cred)
806 def get_trusted_certs(self, opts, args):
808 return uhe trusted certs at this interface
810 trusted_certs = self.registry.get_trusted_certs()
811 for trusted_cert in trusted_certs:
812 gid = GID(string=trusted_cert)
814 cert = Certificate(string=trusted_cert)
815 self.logger.debug('Sfi.get_trusted_certs -> %r'%cert.get_subject())
818 def aggregates(self, opts, args):
820 return a list of details about known aggregates
822 user_cred = self.get_user_cred().save_to_string(save_parents=True)
827 result = self.registry.get_aggregates(user_cred, hrn)
831 def registries(self, opts, args):
833 return a list of details about known registries
835 user_cred = self.get_user_cred().save_to_string(save_parents=True)
839 result = self.registry.get_registries(user_cred, hrn)
844 # ==================================================================
845 # Slice-related commands
846 # ==================================================================
848 def version(self, opts, args):
849 if opts.version_local:
850 version=version_core()
852 if opts.version_registry:
855 server = self.get_server_from_opts(opts)
856 version=server.GetVersion()
857 for (k,v) in version.iteritems():
858 print "%-20s: %s"%(k,v)
860 # list instantiated slices
861 def slices(self, opts, args):
863 list instantiated slices
865 user_cred = self.get_user_cred().save_to_string(save_parents=True)
868 delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority))
869 creds.append(delegated_cred)
870 server = self.get_server_from_opts(opts)
871 #results = server.ListSlices(creds, unique_call_id())
872 results = server.ListSlices(creds)
873 display_list(results)
876 # show rspec for named slice
877 def resources(self, opts, args):
878 user_cred = self.get_user_cred().save_to_string(save_parents=True)
879 server = self.slicemgr
881 server = self.get_server_from_opts(opts)
884 cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
886 call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
893 delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
894 creds.append(delegated_cred)
895 if opts.rspec_version:
896 call_options['rspec_version'] = opts.rspec_version
897 #panos add info options
899 call_options['info'] = opts.info
901 call_args = [creds, call_options]
902 if self.server_supports_call_id_arg(server):
903 call_args.append(unique_call_id())
904 result = server.ListResources(*call_args)
906 if opts.file is None:
907 display_rspec(result, format)
910 if not file.startswith(os.sep):
911 file = os.path.join(self.options.sfi_dir, file)
912 save_rspec_to_file(result, file)
915 # created named slice with given rspec
916 def create(self, opts, args):
918 slice_urn = hrn_to_urn(slice_hrn, 'slice')
919 user_cred = self.get_user_cred()
920 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
923 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
924 creds.append(delegated_cred)
925 rspec_file = self.get_rspec_file(args[1])
926 rspec = open(rspec_file).read()
929 # { urn: urn:publicid:IDN+emulab.net+user+alice
930 # keys: [<ssh key A>, <ssh key B>]
933 server = self.get_server_from_opts(opts)
934 version = server.GetVersion()
935 if 'sfa' not in version:
936 # need to pass along user keys if this request is going to a ProtoGENI aggregate
937 # ProtoGeni Aggregates will only install the keys of the user that is issuing the
938 # request. So we will only pass in one user that contains the keys for all
940 user = {'urn': user_cred.get_gid_caller().get_urn(),
942 slice_record = self.registry.Resolve(slice_urn, creds)
943 if slice_record and 'researchers' in slice_record:
944 user_hrns = slice_record['researchers']
945 user_urns = [hrn_to_urn(hrn, 'user') for hrn in user_hrns]
946 user_records = self.registry.Resolve(user_urns, creds)
947 for user_record in user_records:
948 if 'keys' in user_record:
949 user['keys'].extend(user_record['keys'])
952 call_args = [slice_urn, creds, rspec, users]
953 if self.server_supports_call_id_arg(server):
954 call_args.append(unique_call_id())
956 result = server.CreateSliver(*call_args)
960 # get a ticket for the specified slice
961 def get_ticket(self, opts, args):
962 slice_hrn, rspec_path = args[0], args[1]
963 slice_urn = hrn_to_urn(slice_hrn, 'slice')
964 user_cred = self.get_user_cred()
965 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
968 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
969 creds.append(delegated_cred)
970 rspec_file = self.get_rspec_file(rspec_path)
971 rspec = open(rspec_file).read()
972 server = self.get_server_from_opts(opts)
973 ticket_string = server.GetTicket(slice_urn, creds, rspec, [])
974 file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
975 self.logger.info("writing ticket to %s"%file)
976 ticket = SfaTicket(string=ticket_string)
977 ticket.save_to_file(filename=file, save_parents=True)
979 def redeem_ticket(self, opts, args):
980 ticket_file = args[0]
982 # get slice hrn from the ticket
983 # use this to get the right slice credential
984 ticket = SfaTicket(filename=ticket_file)
986 slice_hrn = ticket.gidObject.get_hrn()
987 slice_urn = hrn_to_urn(slice_hrn, 'slice')
988 #slice_hrn = ticket.attributes['slivers'][0]['hrn']
989 user_cred = self.get_user_cred()
990 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
992 # get a list of node hostnames from the RSpec
993 tree = etree.parse(StringIO(ticket.rspec))
994 root = tree.getroot()
995 hostnames = root.xpath("./network/site/node/hostname/text()")
997 # create an xmlrpc connection to the component manager at each of these
998 # components and gall redeem_ticket
1000 for hostname in hostnames:
1002 self.logger.info("Calling redeem_ticket at %(hostname)s " % locals())
1003 server = self.get_server(hostname, CM_PORT, self.key_file, \
1004 self.cert_file, self.options.debug)
1005 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
1006 self.logger.info("Success")
1007 except socket.gaierror:
1008 self.logger.error("redeem_ticket failed: Component Manager not accepting requests")
1009 except Exception, e:
1010 self.logger.log_exc(e.message)
1013 # delete named slice
1014 def delete(self, opts, args):
1016 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1017 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
1018 creds = [slice_cred]
1020 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1021 creds.append(delegated_cred)
1022 server = self.get_server_from_opts(opts)
1024 call_args = [slice_urn, creds]
1025 if self.server_supports_call_id_arg(server):
1026 call_args.append(unique_call_id())
1027 return server.DeleteSliver(*call_args)
1030 def start(self, opts, args):
1032 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1033 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1034 creds = [slice_cred]
1036 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1037 creds.append(delegated_cred)
1038 server = self.get_server_from_opts(opts)
1039 return server.Start(slice_urn, creds)
1042 def stop(self, opts, args):
1044 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1045 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1046 creds = [slice_cred]
1048 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1049 creds.append(delegated_cred)
1050 server = self.get_server_from_opts(opts)
1051 return server.Stop(slice_urn, creds)
1054 def reset(self, opts, args):
1056 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1057 server = self.get_server_from_opts(opts)
1058 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1059 creds = [slice_cred]
1061 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1062 creds.append(delegated_cred)
1063 return server.reset_slice(creds, slice_urn)
1065 def renew(self, opts, args):
1067 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1068 server = self.get_server_from_opts(opts)
1069 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1070 creds = [slice_cred]
1072 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1073 creds.append(delegated_cred)
1076 call_args = [slice_urn, creds, time]
1077 if self.server_supports_call_id_arg(server):
1078 call_args.append(unique_call_id())
1079 return server.RenewSliver(*call_args)
1082 def status(self, opts, args):
1084 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1085 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
1086 creds = [slice_cred]
1088 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1089 creds.append(delegated_cred)
1090 server = self.get_server_from_opts(opts)
1091 call_args = [slice_urn, creds]
1092 if self.server_supports_call_id_arg(server):
1093 call_args.append(unique_call_id())
1094 print server.SliverStatus(*call_args)
1097 def shutdown(self, opts, args):
1099 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1100 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
1101 creds = [slice_cred]
1103 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1104 creds.append(delegated_cred)
1105 server = self.get_server_from_opts(opts)
1106 return server.Shutdown(slice_urn, creds)
1108 def print_help (self):
1109 self.sfi_parser.print_help()
1110 self.cmd_parser.print_help()
1113 # Main: parse arguments and dispatch to command
1116 self.sfi_parser = self.create_parser()
1117 (options, args) = self.sfi_parser.parse_args()
1118 self.options = options
1120 self.logger.setLevelFromOptVerbose(self.options.verbose)
1121 if options.hashrequest:
1122 self.hashrequest = True
1125 self.logger.critical("No command given. Use -h for help.")
1129 self.cmd_parser = self.create_cmd_parser(command)
1130 (cmd_opts, cmd_args) = self.cmd_parser.parse_args(args[1:])
1133 self.logger.info("Command=%s" % command)
1134 if command in ("resources"):
1135 self.logger.debug("resources cmd_opts %s" % cmd_opts.format)
1136 elif command in ("list", "show", "remove"):
1137 self.logger.debug("cmd_opts.type %s" % cmd_opts.type)
1138 self.logger.debug('cmd_args %s' % cmd_args)
1141 self.dispatch(command, cmd_opts, cmd_args)
1143 self.logger.critical ("Unknown command %s"%command)
1148 if __name__ == "__main__":