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 sfa_logger,sfa_logger_goes_to_console
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 sfa_logger_goes_to_console()
145 self.logger=sfa_logger()
147 def create_cmd_parser(self, command, additional_cmdargs=None):
148 cmdargs = {"list": "authority",
153 "aggregates": "[name]",
154 "registries": "[name]",
156 "get_trusted_certs": "cred",
158 "resources": "[name]",
159 "create": "name rspec",
160 "get_ticket": "name rspec",
161 "redeem_ticket": "ticket",
173 if additional_cmdargs:
174 cmdargs.update(additional_cmdargs)
176 if command not in cmdargs:
177 msg="Invalid command\n"
179 msg += ','.join(cmdargs.keys())
180 self.logger.critical(msg)
183 parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
184 % (command, cmdargs[command]))
186 # user specifies remote aggregate/sm/component
187 if command in ("resources", "slices", "create", "delete", "start", "stop",
188 "restart", "shutdown", "get_ticket", "renew", "status"):
189 parser.add_option("-a", "--aggregate", dest="aggregate",
190 default=None, help="aggregate host")
191 parser.add_option("-p", "--port", dest="port",
192 default=AGGREGATE_PORT, help="aggregate port")
193 parser.add_option("-c", "--component", dest="component", default=None,
194 help="component hrn")
195 parser.add_option("-d", "--delegate", dest="delegate", default=None,
197 help="Include a credential delegated to the user's root"+\
198 "authority in set of credentials for this call")
200 # registy filter option
201 if command in ("list", "show", "remove"):
202 parser.add_option("-t", "--type", dest="type", type="choice",
203 help="type filter ([all]|user|slice|authority|node|aggregate)",
204 choices=("all", "user", "slice", "authority", "node", "aggregate"),
207 if command in ("resources"):
208 parser.add_option("-r", "--rspec-version", dest="rspec_version", default="SFA 1",
209 help="schema type and version of resulting RSpec")
210 parser.add_option("-f", "--format", dest="format", type="choice",
211 help="display format ([xml]|dns|ip)", default="xml",
212 choices=("xml", "dns", "ip"))
213 #panos: a new option to define the type of information about resources a user is interested in
214 parser.add_option("-i", "--info", dest="info",
215 help="optional component information", default=None)
218 if command in ("resources", "show", "list"):
219 parser.add_option("-o", "--output", dest="file",
220 help="output XML to file", metavar="FILE", default=None)
222 if command in ("show", "list"):
223 parser.add_option("-f", "--format", dest="format", type="choice",
224 help="display format ([text]|xml)", default="text",
225 choices=("text", "xml"))
227 if command in ("delegate"):
228 parser.add_option("-u", "--user",
229 action="store_true", dest="delegate_user", default=False,
230 help="delegate user credential")
231 parser.add_option("-s", "--slice", dest="delegate_slice",
232 help="delegate slice credential", metavar="HRN", default=None)
234 if command in ("version"):
235 parser.add_option("-a", "--aggregate", dest="aggregate",
236 default=None, help="aggregate host")
237 parser.add_option("-p", "--port", dest="port",
238 default=AGGREGATE_PORT, help="aggregate port")
239 parser.add_option("-R","--registry-version",
240 action="store_true", dest="version_registry", default=False,
241 help="probe registry version instead of slicemgr")
242 parser.add_option("-l","--local",
243 action="store_true", dest="version_local", default=False,
244 help="display version of the local client")
249 def create_parser(self):
251 # Generate command line parser
252 parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
253 description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
254 parser.add_option("-r", "--registry", dest="registry",
255 help="root registry", metavar="URL", default=None)
256 parser.add_option("-s", "--slicemgr", dest="sm",
257 help="slice manager", metavar="URL", default=None)
258 default_sfi_dir = os.path.expanduser("~/.sfi/")
259 parser.add_option("-d", "--dir", dest="sfi_dir",
260 help="config & working directory - default is " + default_sfi_dir,
261 metavar="PATH", default=default_sfi_dir)
262 parser.add_option("-u", "--user", dest="user",
263 help="user name", metavar="HRN", default=None)
264 parser.add_option("-a", "--auth", dest="auth",
265 help="authority name", metavar="HRN", default=None)
266 parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0,
267 help="verbose mode - cumulative")
268 parser.add_option("-D", "--debug",
269 action="store_true", dest="debug", default=False,
270 help="Debug (xml-rpc) protocol messages")
271 parser.add_option("-p", "--protocol", dest="protocol", default="xmlrpc",
272 help="RPC protocol (xmlrpc or soap)")
273 parser.add_option("-k", "--hashrequest",
274 action="store_true", dest="hashrequest", default=False,
275 help="Create a hash of the request that will be authenticated on the server")
276 parser.disable_interspersed_args()
281 def read_config(self):
282 config_file = self.options.sfi_dir + os.sep + "sfi_config"
284 config = Config (config_file)
286 self.logger.critical("Failed to read configuration file %s"%config_file)
287 self.logger.info("Make sure to remove the export clauses and to add quotes")
288 if self.options.verbose==0:
289 self.logger.info("Re-run with -v for more details")
291 self.logger.log_exc("Could not read config file %s"%config_file)
296 if (self.options.sm is not None):
297 self.sm_url = self.options.sm
298 elif hasattr(config, "SFI_SM"):
299 self.sm_url = config.SFI_SM
301 self.logger.error("You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file)
305 if (self.options.registry is not None):
306 self.reg_url = self.options.registry
307 elif hasattr(config, "SFI_REGISTRY"):
308 self.reg_url = config.SFI_REGISTRY
310 self.logger.errors("You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file)
315 if (self.options.user is not None):
316 self.user = self.options.user
317 elif hasattr(config, "SFI_USER"):
318 self.user = config.SFI_USER
320 self.logger.errors("You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file)
324 if (self.options.auth is not None):
325 self.authority = self.options.auth
326 elif hasattr(config, "SFI_AUTH"):
327 self.authority = config.SFI_AUTH
329 self.logger.error("You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file)
337 # Establish Connection to SliceMgr and Registry Servers
339 def set_servers(self):
342 # Get key and certificate
343 key_file = self.get_key_file()
344 cert_file = self.get_cert_file(key_file)
345 self.key = Keypair(filename=key_file)
346 self.key_file = key_file
347 self.cert_file = cert_file
348 self.cert = GID(filename=cert_file)
349 # Establish connection to server(s)
350 self.logger.info("Contacting Registry at: %s"%self.reg_url)
351 self.registry = xmlrpcprotocol.get_server(self.reg_url, key_file, cert_file, self.options)
352 self.logger.info("Contacting Slice Manager at: %s"%self.sm_url)
353 self.slicemgr = xmlrpcprotocol.get_server(self.sm_url, key_file, cert_file, self.options)
357 def get_cached_server_version(self, server):
358 # check local cache first
361 cache_file = self.sfi_dir + os.path.sep + 'sfi_cache.dat'
362 cache_key = server.url + "-version"
364 cache = Cache(cache_file)
367 self.logger.info("Local cache not found at: %s" % cache_file)
370 version = cache.get(cache_key)
373 version = server.GetVersion()
374 # cache version for 24 hours
375 cache.add(cache_key, version, ttl= 60*60*24)
381 def server_supports_call_id_arg(self, server):
383 Returns true if server support the optional call_id arg, false otherwise.
385 server_version = self.get_cached_server_version(server)
386 if 'sfa' in server_version:
387 code_tag = server_version['code_tag']
388 code_tag_parts = code_tag.split("-")
390 version_parts = code_tag_parts[0].split(".")
391 major, minor = version_parts[0], version_parts[1]
392 rev = code_tag_parts[1]
394 if int(minor) > 0 or int(rev) > 20:
399 # Get various credential and spec files
401 # Establishes limiting conventions
402 # - conflates MAs and SAs
403 # - assumes last token in slice name is unique
405 # Bootstraps credentials
406 # - bootstrap user credential from self-signed certificate
407 # - bootstrap authority credential from user credential
408 # - bootstrap slice credential from user credential
412 def get_key_file(self):
413 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
414 if (os.path.isfile(file)):
417 self.logger.error("Key file %s does not exist"%file)
421 def get_cert_file(self, key_file):
423 cert_file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
424 if (os.path.isfile(cert_file)):
425 # we'd perfer to use Registry issued certs instead of self signed certs.
426 # if this is a Registry cert (GID) then we are done
427 gid = GID(filename=cert_file)
431 # generate self signed certificate
432 k = Keypair(filename=key_file)
433 cert = Certificate(subject=self.user)
435 cert.set_issuer(k, self.user)
437 self.logger.info("Writing self-signed certificate to %s"%cert_file)
438 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")
484 gid = self.get_cached_gid(gidfile)
486 user_cred = self.get_user_cred()
487 records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
491 if type == record['type']:
494 raise RecordNotFound(args[0])
495 gid = GID(string=records[0]['gid'])
496 self.logger.info("Writing gid to %s"%gidfile)
497 gid.save_to_file(filename=gidfile)
501 def get_cached_credential(self, file):
503 Return a cached credential only if it hasn't expired.
505 if (os.path.isfile(file)):
506 credential = Credential(filename=file)
507 # make sure it isnt expired
508 if not credential.get_expiration or \
509 datetime.datetime.today() < credential.get_expiration():
513 def get_user_cred(self):
514 file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
515 return self.get_cred(file, 'user', self.user)
517 def get_auth_cred(self):
518 if not self.authority:
519 self.logger.critical("no authority specified. Use -a or set SF_AUTH")
521 file = os.path.join(self.options.sfi_dir, self.authority + ".cred")
522 return self.get_cred(file, 'authority', self.authority)
524 def get_slice_cred(self, name):
525 file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
526 return self.get_cred(file, 'slice', name)
528 def get_cred(self, file, type, hrn):
529 # attempt to load a cached credential
530 cred = self.get_cached_credential(file)
533 cert_string = self.cert.save_to_string(save_parents=True)
534 user_name = self.user.replace(self.authority + ".", '')
535 if user_name.count(".") > 0:
536 user_name = user_name.replace(".", '_')
537 self.user = self.authority + "." + user_name
538 cred_str = self.registry.GetSelfCredential(cert_string, hrn, "user")
540 # bootstrap slice credential from user credential
541 user_cred = self.get_user_cred().save_to_string(save_parents=True)
542 cred_str = self.registry.GetCredential(user_cred, hrn, type)
545 self.logger.critical("Failed to get %s credential" % type)
548 cred = Credential(string=cred_str)
549 cred.save_to_file(file, save_parents=True)
550 self.logger.info("Writing %s credential to %s" %(type, file))
555 def get_rspec_file(self, rspec):
556 if (os.path.isabs(rspec)):
559 file = os.path.join(self.options.sfi_dir, rspec)
560 if (os.path.isfile(file)):
563 self.logger.critical("No such rspec file %s"%rspec)
566 def get_record_file(self, record):
567 if (os.path.isabs(record)):
570 file = os.path.join(self.options.sfi_dir, record)
571 if (os.path.isfile(file)):
574 self.logger.critical("No such registry record file %s"%record)
577 def load_publickey_string(self, fn):
579 key_string = f.read()
581 # if the filename is a private key file, then extract the public key
582 if "PRIVATE KEY" in key_string:
583 outfn = tempfile.mktemp()
584 cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
587 key_string = f.read()
593 def get_component_server_from_hrn(self, hrn):
594 # direct connection to the nodes component manager interface
595 user_cred = self.get_user_cred().save_to_string(save_parents=True)
596 records = self.registry.Resolve(hrn, user_cred)
597 records = filter_records('node', records)
599 self.logger.warning("No such component:%r"% opts.component)
602 return self.get_server(record['hostname'], CM_PORT, self.key_file, self.cert_file)
604 def get_server(self, host, port, keyfile, certfile):
606 Return an instance of an xmlrpc server connection
608 # port is appended onto the domain, before the path. Should look like:
609 # http://domain:port/path
610 host_parts = host.split('/')
611 host_parts[0] = host_parts[0] + ":" + str(port)
612 url = "http://%s" % "/".join(host_parts)
613 return xmlrpcprotocol.get_server(url, keyfile, certfile, self.options)
615 # xxx opts could be retrieved in self.options
616 def get_server_from_opts(self, opts):
618 Return instance of an xmlrpc connection to a slice manager, aggregate
619 or component server depending on the specified opts
621 server = self.slicemgr
622 # direct connection to an aggregate
623 if hasattr(opts, 'aggregate') and opts.aggregate:
624 server = self.get_server(opts.aggregate, opts.port, self.key_file, self.cert_file)
625 # direct connection to the nodes component manager interface
626 if hasattr(opts, 'component') and opts.component:
627 server = self.get_component_server_from_hrn(opts.component)
630 #==========================================================================
631 # Following functions implement the commands
633 # Registry-related commands
634 #==========================================================================
636 def dispatch(self, command, cmd_opts, cmd_args):
637 return getattr(self, command)(cmd_opts, cmd_args)
639 # list entires in named authority registry
640 def list(self, opts, args):
645 user_cred = self.get_user_cred().save_to_string(save_parents=True)
647 list = self.registry.List(hrn, user_cred)
649 raise Exception, "Not enough parameters for the 'list' command"
651 # filter on person, slice, site, node, etc.
652 # THis really should be in the self.filter_records funct def comment...
653 list = filter_records(opts.type, list)
655 print "%s (%s)" % (record['hrn'], record['type'])
658 if not file.startswith(os.sep):
659 file = os.path.join(self.options.sfi_dir, file)
660 save_records_to_file(file, list)
663 # show named registry record
664 def show(self, opts, args):
669 user_cred = self.get_user_cred().save_to_string(save_parents=True)
670 records = self.registry.Resolve(hrn, user_cred)
671 records = filter_records(opts.type, records)
673 print "No record of type", opts.type
674 for record in records:
675 if record['type'] in ['user']:
676 record = UserRecord(dict=record)
677 elif record['type'] in ['slice']:
678 record = SliceRecord(dict=record)
679 elif record['type'] in ['node']:
680 record = NodeRecord(dict=record)
681 elif record['type'] in ['authority', 'ma', 'sa']:
682 record = AuthorityRecord(dict=record)
684 record = SfaRecord(dict=record)
685 if (opts.format == "text"):
688 print record.save_to_string()
692 if not file.startswith(os.sep):
693 file = os.path.join(self.options.sfi_dir, file)
694 save_records_to_file(file, records)
697 def delegate(self, opts, args):
699 delegee_hrn = args[0]
700 if opts.delegate_user:
701 user_cred = self.get_user_cred()
702 cred = self.delegate_cred(user_cred, delegee_hrn)
703 elif opts.delegate_slice:
704 slice_cred = self.get_slice_cred(opts.delegate_slice)
705 cred = self.delegate_cred(slice_cred, delegee_hrn)
707 self.logger.warning("Must specify either --user or --slice <hrn>")
709 delegated_cred = Credential(string=cred)
710 object_hrn = delegated_cred.get_gid_object().get_hrn()
711 if opts.delegate_user:
712 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
713 + get_leaf(object_hrn) + ".cred")
714 elif opts.delegate_slice:
715 dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
716 + get_leaf(object_hrn) + ".cred")
718 delegated_cred.save_to_file(dest_fn, save_parents=True)
720 self.logger.info("delegated credential for %s to %s and wrote to %s"%(object_hrn, delegee_hrn,dest_fn))
722 def delegate_cred(self, object_cred, hrn):
723 # the gid and hrn of the object we are delegating
724 if isinstance(object_cred, str):
725 object_cred = Credential(string=object_cred)
726 object_gid = object_cred.get_gid_object()
727 object_hrn = object_gid.get_hrn()
729 if not object_cred.get_privileges().get_all_delegate():
730 self.logger.error("Object credential %s does not have delegate bit set"%object_hrn)
733 # the delegating user's gid
734 caller_gid = self._get_gid(self.user)
735 caller_gidfile = os.path.join(self.options.sfi_dir, self.user + ".gid")
737 # the gid of the user who will be delegated to
738 delegee_gid = self._get_gid(hrn)
739 delegee_hrn = delegee_gid.get_hrn()
740 delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
741 delegee_gid.save_to_file(filename=delegee_gidfile)
742 dcred = object_cred.delegate(delegee_gidfile, self.get_key_file(), caller_gidfile)
743 return dcred.save_to_string(save_parents=True)
745 # removed named registry record
746 # - have to first retrieve the record to be removed
747 def remove(self, opts, args):
748 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
756 return self.registry.Remove(hrn, auth_cred, type)
758 # add named registry record
759 def add(self, opts, args):
760 auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
764 record_filepath = args[0]
765 rec_file = self.get_record_file(record_filepath)
766 record = load_record_from_file(rec_file).as_dict()
767 return self.registry.Register(record, auth_cred)
769 # update named registry entry
770 def update(self, opts, args):
771 user_cred = self.get_user_cred()
775 rec_file = self.get_record_file(args[0])
776 record = load_record_from_file(rec_file)
777 if record['type'] == "user":
778 if record.get_name() == user_cred.get_gid_object().get_hrn():
779 cred = user_cred.save_to_string(save_parents=True)
781 cred = self.get_auth_cred().save_to_string(save_parents=True)
782 elif record['type'] in ["slice"]:
784 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
785 except xmlrpcprotocol.ServerException, e:
786 # XXX smbaker -- once we have better error return codes, update this
787 # to do something better than a string compare
788 if "Permission error" in e.args[0]:
789 cred = self.get_auth_cred().save_to_string(save_parents=True)
792 elif record.get_type() in ["authority"]:
793 cred = self.get_auth_cred().save_to_string(save_parents=True)
794 elif record.get_type() == 'node':
795 cred = self.get_auth_cred().save_to_string(save_parents=True)
797 raise "unknown record type" + record.get_type()
798 record = record.as_dict()
799 return self.registry.Update(record, cred)
801 def get_trusted_certs(self, opts, args):
803 return uhe trusted certs at this interface
805 trusted_certs = self.registry.get_trusted_certs()
806 for trusted_cert in trusted_certs:
807 cert = Certificate(string=trusted_cert)
808 self.logger.debug('Sfi.get_trusted_certs -> %r'%cert.get_subject())
811 def aggregates(self, opts, args):
813 return a list of details about known aggregates
815 user_cred = self.get_user_cred().save_to_string(save_parents=True)
820 result = self.registry.get_aggregates(user_cred, hrn)
824 def registries(self, opts, args):
826 return a list of details about known registries
828 user_cred = self.get_user_cred().save_to_string(save_parents=True)
832 result = self.registry.get_registries(user_cred, hrn)
837 # ==================================================================
838 # Slice-related commands
839 # ==================================================================
841 def version(self, opts, args):
842 if opts.version_local:
843 version=version_core()
845 if opts.version_registry:
848 server = self.get_server_from_opts(opts)
849 version=server.GetVersion()
850 for (k,v) in version.iteritems():
851 print "%-20s: %s"%(k,v)
853 # list instantiated slices
854 def slices(self, opts, args):
856 list instantiated slices
858 user_cred = self.get_user_cred().save_to_string(save_parents=True)
861 delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority))
862 creds.append(delegated_cred)
863 server = self.get_server_from_opts(opts)
864 #results = server.ListSlices(creds, unique_call_id())
865 results = server.ListSlices(creds)
866 display_list(results)
869 # show rspec for named slice
870 def resources(self, opts, args):
871 user_cred = self.get_user_cred().save_to_string(save_parents=True)
872 server = self.slicemgr
874 server = self.get_server_from_opts(opts)
877 cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
879 call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
886 delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
887 creds.append(delegated_cred)
888 if opts.rspec_version:
889 call_options['rspec_version'] = opts.rspec_version
890 #panos add info options
892 call_options['info'] = opts.info
894 server_version = self.get_cached_server_version(server)
895 if self.server_supports_call_id_arg(server):
896 result = server.ListResources(creds, call_options,unique_call_id())
898 result = server.ListResources(creds, call_options)
900 if opts.file is None:
901 display_rspec(result, format)
904 if not file.startswith(os.sep):
905 file = os.path.join(self.options.sfi_dir, file)
906 save_rspec_to_file(result, file)
909 # created named slice with given rspec
910 def create(self, opts, args):
912 slice_urn = hrn_to_urn(slice_hrn, 'slice')
913 user_cred = self.get_user_cred()
914 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
917 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
918 creds.append(delegated_cred)
919 rspec_file = self.get_rspec_file(args[1])
920 rspec = open(rspec_file).read()
923 # { urn: urn:publicid:IDN+emulab.net+user+alice
924 # keys: [<ssh key A>, <ssh key B>]
927 server = self.get_server_from_opts(opts)
928 version = server.GetVersion()
929 if 'sfa' not in version:
930 # need to pass along user keys if this request is going to a ProtoGENI aggregate
931 # ProtoGeni Aggregates will only install the keys of the user that is issuing the
932 # request. So we will only pass in one user that contains the keys for all
934 user = {'urn': user_cred.get_gid_caller().get_urn(),
936 slice_record = self.registry.Resolve(slice_urn, creds)
937 if slice_record and 'researchers' in slice_record:
938 user_hrns = slice_record['researchers']
939 user_urns = [hrn_to_urn(hrn, 'user') for hrn in user_hrns]
940 user_records = self.registry.Resolve(user_urns, creds)
941 for user_record in user_records:
942 if 'keys' in user_record:
943 user['keys'].extend(user_record['keys'])
945 result = server.CreateSliver(slice_urn, creds, rspec, users, unique_call_id())
949 # get a ticket for the specified slice
950 def get_ticket(self, opts, args):
951 slice_hrn, rspec_path = args[0], args[1]
952 slice_urn = hrn_to_urn(slice_hrn, 'slice')
953 user_cred = self.get_user_cred()
954 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
957 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
958 creds.append(delegated_cred)
959 rspec_file = self.get_rspec_file(rspec_path)
960 rspec = open(rspec_file).read()
961 server = self.get_server_from_opts(opts)
962 ticket_string = server.GetTicket(slice_urn, creds, rspec, [])
963 file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
964 self.logger.info("writing ticket to %s"%file)
965 ticket = SfaTicket(string=ticket_string)
966 ticket.save_to_file(filename=file, save_parents=True)
968 def redeem_ticket(self, opts, args):
969 ticket_file = args[0]
971 # get slice hrn from the ticket
972 # use this to get the right slice credential
973 ticket = SfaTicket(filename=ticket_file)
975 slice_hrn = ticket.gidObject.get_hrn()
976 slice_urn = hrn_to_urn(slice_hrn, 'slice')
977 #slice_hrn = ticket.attributes['slivers'][0]['hrn']
978 user_cred = self.get_user_cred()
979 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
981 # get a list of node hostnames from the RSpec
982 tree = etree.parse(StringIO(ticket.rspec))
983 root = tree.getroot()
984 hostnames = root.xpath("./network/site/node/hostname/text()")
986 # create an xmlrpc connection to the component manager at each of these
987 # components and gall redeem_ticket
989 for hostname in hostnames:
991 self.logger.info("Calling redeem_ticket at %(hostname)s " % locals())
992 server = self.get_server(hostname, CM_PORT, self.key_file, \
993 self.cert_file, self.options.debug)
994 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
995 self.logger.info("Success")
996 except socket.gaierror:
997 self.logger.error("redeem_ticket failed: Component Manager not accepting requests")
999 self.logger.log_exc(e.message)
1002 # delete named slice
1003 def delete(self, opts, args):
1005 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1006 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
1007 creds = [slice_cred]
1009 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1010 creds.append(delegated_cred)
1011 server = self.get_server_from_opts(opts)
1012 return server.DeleteSliver(slice_urn, creds, unique_call_id())
1015 def start(self, opts, args):
1017 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1018 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1019 creds = [slice_cred]
1021 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1022 creds.append(delegated_cred)
1023 server = self.get_server_from_opts(opts)
1024 return server.Start(slice_urn, creds)
1027 def stop(self, opts, args):
1029 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1030 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1031 creds = [slice_cred]
1033 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1034 creds.append(delegated_cred)
1035 server = self.get_server_from_opts(opts)
1036 return server.Stop(slice_urn, creds)
1039 def reset(self, opts, args):
1041 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1042 server = self.get_server_from_opts(opts)
1043 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1044 creds = [slice_cred]
1046 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1047 creds.append(delegated_cred)
1048 return server.reset_slice(creds, slice_urn)
1050 def renew(self, opts, args):
1052 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1053 server = self.get_server_from_opts(opts)
1054 slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
1055 creds = [slice_cred]
1057 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1058 creds.append(delegated_cred)
1060 return server.RenewSliver(slice_urn, creds, time, unique_call_id())
1063 def status(self, opts, args):
1065 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1066 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
1067 creds = [slice_cred]
1069 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1070 creds.append(delegated_cred)
1071 server = self.get_server_from_opts(opts)
1072 print server.SliverStatus(slice_urn, creds, unique_call_id())
1075 def shutdown(self, opts, args):
1077 slice_urn = hrn_to_urn(slice_hrn, 'slice')
1078 slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
1079 creds = [slice_cred]
1081 delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
1082 creds.append(delegated_cred)
1083 server = self.get_server_from_opts(opts)
1084 return server.Shutdown(slice_urn, creds)
1086 def print_help (self):
1087 self.sfi_parser.print_help()
1088 self.cmd_parser.print_help()
1091 # Main: parse arguments and dispatch to command
1094 self.sfi_parser = self.create_parser()
1095 (options, args) = self.sfi_parser.parse_args()
1096 self.options = options
1098 self.logger.setLevelFromOptVerbose(self.options.verbose)
1099 if options.hashrequest:
1100 self.hashrequest = True
1103 self.logger.critical("No command given. Use -h for help.")
1107 self.cmd_parser = self.create_cmd_parser(command)
1108 (cmd_opts, cmd_args) = self.cmd_parser.parse_args(args[1:])
1112 self.logger.info("Command=%s" % command)
1113 if command in ("resources"):
1114 self.logger.debug("resources cmd_opts %s" % cmd_opts.format)
1115 elif command in ("list", "show", "remove"):
1116 self.logger.debug("cmd_opts.type %s" % cmd_opts.type)
1117 self.logger.debug('cmd_args %s',cmd_args)
1120 self.dispatch(command, cmd_opts, cmd_args)
1122 self.logger.critical ("Unknown command %s"%command)
1127 if __name__ == "__main__":