on client (sfi.py), when verbose flag is given print xml-rpc method calls.
[sfa.git] / sfa / client / sfi.py
1 #! /usr/bin/env python
2
3 # sfi -- slice-based facility interface
4
5 import sys
6 sys.path.append('.')
7 import os, os.path
8 import tempfile
9 import traceback
10 import socket
11 import random
12 import datetime
13 from lxml import etree
14 from StringIO import StringIO
15 from types import StringTypes, ListType
16 from optparse import OptionParser
17 from sfa.trust.certificate import Keypair, Certificate
18 from sfa.trust.credential import Credential
19 from sfa.util.sfaticket import SfaTicket
20 from sfa.util.record import *
21 from sfa.util.namespace import *
22 from sfa.util.xmlrpcprotocol import ServerException
23 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
24 from sfa.util.config import Config
25 import zlib
26
27 AGGREGATE_PORT=12346
28 CM_PORT=12346
29
30 # utility methods here
31 # display methods
32 def display_rspec(rspec, format='rspec'):
33     if format in ['dns']:
34         tree = etree.parse(StringIO(rspec))
35         root = tree.getroot()
36         result = root.xpath("./network/site/node/hostname/text()")
37     elif format in ['ip']:
38         # The IP address is not yet part of the new RSpec
39         # so this doesn't do anything yet.
40         tree = etree.parse(StringIO(rspec))
41         root = tree.getroot()
42         result = root.xpath("./network/site/node/ipv4/text()")
43     else:
44         result = rspec
45
46     print result
47     return
48
49 def display_list(results):
50     for result in results:
51         print result
52
53 def display_records(recordList, dump=False):
54     ''' Print all fields in the record'''
55     for record in recordList:
56         display_record(record, dump)
57
58 def display_record(record, dump=False):
59     if dump:
60         record.dump()
61     else:
62         info = record.getdict()
63         print "%s (%s)" % (info['hrn'], info['type'])
64     return
65
66
67 def filter_records(type, records):
68     filtered_records = []
69     for record in records:
70         if (record['type'] == type) or (type == "all"):
71             filtered_records.append(record)
72     return filtered_records
73
74
75 # save methods
76 def save_rspec_to_file(rspec, filename):
77     if not filename.endswith(".rspec"):
78         filename = filename + ".rspec"
79
80     f = open(filename, 'w')
81     f.write(rspec)
82     f.close()
83     return
84
85 def save_records_to_file(filename, recordList):
86     index = 0
87     for record in recordList:
88         if index > 0:
89             save_record_to_file(filename + "." + str(index), record)
90         else:
91             save_record_to_file(filename, record)
92         index = index + 1
93
94 def save_record_to_file(filename, record):
95     if record['type'] in ['user']:
96         record = UserRecord(dict=record)
97     elif record['type'] in ['slice']:
98         record = SliceRecord(dict=record)
99     elif record['type'] in ['node']:
100         record = NodeRecord(dict=record)
101     elif record['type'] in ['authority', 'ma', 'sa']:
102         record = AuthorityRecord(dict=record)
103     else:
104         record = SfaRecord(dict=record)
105     str = record.save_to_string()
106     file(filename, "w").write(str)
107     return
108
109
110 # load methods
111 def load_record_from_file(filename):
112     str = file(filename, "r").read()
113     record = SfaRecord(string=str)
114     return record
115
116
117
118 class Sfi:
119
120     slicemgr = None
121     registry = None
122     user = None
123     authority = None
124     options = None
125     hashrequest = False
126    
127     def create_cmd_parser(self, command, additional_cmdargs=None):
128         cmdargs = {"list": "name",
129                   "show": "name",
130                   "remove": "name",
131                   "add": "record",
132                   "update": "record",
133                   "aggregates": "[name]",
134                   "registries": "[name]",
135                   "get_gid": [],  
136                   "get_trusted_certs": "cred",
137                   "slices": "",
138                   "resources": "[name]",
139                   "create": "name rspec",
140                   "get_ticket": "name rspec",
141                   "redeem_ticket": "ticket",
142                   "delete": "name",
143                   "reset": "name",
144                   "start": "name",
145                   "stop": "name",
146                   "delegate": "name",
147                   "status": "name",
148                   "renew": "name",
149                   "shutdown": "name",
150                   "version": "",  
151                  }
152
153         if additional_cmdargs:
154             cmdargs.update(additional_cmdargs)
155
156         if command not in cmdargs:
157             print "Invalid command\n"
158             print "Commands: ",
159             for key in cmdargs.keys():
160                 print key + ",",
161             print ""
162             sys.exit(2)
163
164         parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
165                                      % (command, cmdargs[command]))
166
167         # user specifies remote aggregate/sm/component                          
168         if command in ("resources", "slices", "create", "delete", "start", "stop", 
169                        "restart", "shutdown",  "get_ticket", "renew", "status"):
170             parser.add_option("-a", "--aggregate", dest="aggregate",
171                              default=None, help="aggregate host")
172             parser.add_option("-p", "--port", dest="port",
173                              default=AGGREGATE_PORT, help="aggregate port")
174             parser.add_option("-c", "--component", dest="component", default=None,
175                              help="component hrn")
176             parser.add_option("-d", "--delegate", dest="delegate", default=None, 
177                              action="store_true",
178                              help="Include a credential delegated to the user's root"+\
179                                   "authority in set of credentials for this call")  
180         
181         # registy filter option    
182         if command in ("list", "show", "remove"):
183             parser.add_option("-t", "--type", dest="type", type="choice",
184                             help="type filter ([all]|user|slice|authority|node|aggregate)",
185                             choices=("all", "user", "slice", "authority", "node", "aggregate"),
186                             default="all")
187         # display formats
188         if command in ("resources"):
189             parser.add_option("-f", "--format", dest="format", type="choice",
190                              help="display format ([xml]|dns|ip)", default="xml",
191                              choices=("xml", "dns", "ip"))
192
193         if command in ("resources", "show", "list"):
194            parser.add_option("-o", "--output", dest="file",
195                             help="output XML to file", metavar="FILE", default=None)
196         
197         if command in ("show", "list"):
198            parser.add_option("-f", "--format", dest="format", type="choice",
199                              help="display format ([text]|xml)", default="text",
200                              choices=("text", "xml"))
201
202         if command in ("delegate"):
203            parser.add_option("-u", "--user",
204                             action="store_true", dest="delegate_user", default=False,
205                             help="delegate user credential")
206            parser.add_option("-s", "--slice", dest="delegate_slice",
207                             help="delegate slice credential", metavar="HRN", default=None)
208         
209         return parser
210
211         
212     def create_parser(self):
213
214         # Generate command line parser
215         parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
216                              description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
217         parser.add_option("-r", "--registry", dest="registry",
218                          help="root registry", metavar="URL", default=None)
219         parser.add_option("-s", "--slicemgr", dest="sm",
220                          help="slice manager", metavar="URL", default=None)
221         default_sfi_dir = os.path.expanduser("~/.sfi/")
222         parser.add_option("-d", "--dir", dest="sfi_dir",
223                          help="config & working directory - default is " + default_sfi_dir,
224                          metavar="PATH", default=default_sfi_dir)
225         parser.add_option("-u", "--user", dest="user",
226                          help="user name", metavar="HRN", default=None)
227         parser.add_option("-a", "--auth", dest="auth",
228                          help="authority name", metavar="HRN", default=None)
229         parser.add_option("-v", "--verbose",
230                          action="store_true", dest="verbose", default=False,
231                          help="verbose mode")
232         parser.add_option("-D", "--debug",
233                           action="store_true", dest="debug", default=False,
234                           help="Debug (xml-rpc) protocol messages")
235         parser.add_option("-p", "--protocol",
236                          dest="protocol", default="xmlrpc",
237                          help="RPC protocol (xmlrpc or soap)")
238         parser.add_option("-k", "--hashrequest",
239                          action="store_true", dest="hashrequest", default=False,
240                          help="Create a hash of the request that will be authenticated on the server")
241         parser.disable_interspersed_args()
242
243         return parser
244         
245  
246     #
247     # Establish Connection to SliceMgr and Registry Servers
248     #
249     def set_servers(self):
250        config_file = self.options.sfi_dir + os.sep + "sfi_config"
251        try:
252           config = Config (config_file)
253        except:
254           print "Failed to read configuration file", config_file
255           print "Make sure to remove the export clauses and to add quotes"
256           if not self.options.verbose:
257              print "Re-run with -v for more details"
258           else:
259              traceback.print_exc()
260           sys.exit(1)
261     
262        errors = 0
263        # Set SliceMgr URL
264        if (self.options.sm is not None):
265           sm_url = self.options.sm
266        elif hasattr(config, "SFI_SM"):
267           sm_url = config.SFI_SM
268        else:
269           print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file
270           errors += 1 
271     
272        # Set Registry URL
273        if (self.options.registry is not None):
274           reg_url = self.options.registry
275        elif hasattr(config, "SFI_REGISTRY"):
276           reg_url = config.SFI_REGISTRY
277        else:
278           print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file
279           errors += 1 
280           
281
282        # Set user HRN
283        if (self.options.user is not None):
284           self.user = self.options.user
285        elif hasattr(config, "SFI_USER"):
286           self.user = config.SFI_USER
287        else:
288           print "You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file
289           errors += 1 
290     
291        # Set authority HRN
292        if (self.options.auth is not None):
293           self.authority = self.options.auth
294        elif hasattr(config, "SFI_AUTH"):
295           self.authority = config.SFI_AUTH
296        else:
297           print "You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file
298           errors += 1 
299     
300        if errors:
301           sys.exit(1)
302     
303     
304        # Get key and certificate
305        key_file = self.get_key_file()
306        cert_file = self.get_cert_file(key_file)
307        self.key = Keypair(filename=key_file) 
308        self.key_file = key_file
309        self.cert_file = cert_file
310        self.cert = Certificate(filename=cert_file) 
311        # Establish connection to server(s)
312        if self.options.verbose : print "Contacting Registry at:", reg_url
313        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file, self.options)  
314        if self.options.verbose : print "Contacting Slice Manager at:", sm_url
315        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file, self.options)
316
317        return
318     
319     #
320     # Get various credential and spec files
321     #
322     # Establishes limiting conventions
323     #   - conflates MAs and SAs
324     #   - assumes last token in slice name is unique
325     #
326     # Bootstraps credentials
327     #   - bootstrap user credential from self-signed certificate
328     #   - bootstrap authority credential from user credential
329     #   - bootstrap slice credential from user credential
330     #
331     
332     
333     def get_key_file(self):
334        file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
335        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
336        if (os.path.isfile(file)):
337           return file
338        else:
339           print "Key file", file, "does not exist"
340           sys.exit(-1)
341        return
342     
343     def get_cert_file(self, key_file):
344     
345        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
346        file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
347        if (os.path.isfile(file)):
348           return file
349        else:
350           k = Keypair(filename=key_file)
351           cert = Certificate(subject=self.user)
352           cert.set_pubkey(k)
353           cert.set_issuer(k, self.user)
354           cert.sign()
355           if self.options.verbose :
356              print "Writing self-signed certificate to", file
357           cert.save_to_file(file)
358           return file
359
360     def get_cached_gid(self, file):
361         """
362         Return a cached gid    
363         """
364         gid = None 
365         if (os.path.isfile(file)):
366             gid = GID(filename=file)
367         return gid
368
369     def get_gid(self, opts, args):
370         hrn = None
371         if args:
372             hrn = args[0]
373         gid = self._get_gid(hrn)
374         print gid.save_to_string(save_parents=True)
375         return gid
376
377     def _get_gid(self, hrn=None):
378         if not hrn:
379             hrn = self.user
380  
381         gidfile = os.path.join(self.options.sfi_dir, hrn + ".gid")
382         gid = self.get_cached_gid(gidfile)
383         if not gid:
384             user_cred = self.get_user_cred()
385             records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
386             if not records:
387                 raise RecordNotFound(args[0])
388             gid = GID(string=records[0]['gid'])
389             if self.options.verbose:
390                 print "Writing gid to ", gidfile 
391             gid.save_to_file(filename=gidfile)
392         return gid   
393                 
394      
395     def get_cached_credential(self, file):
396         """
397         Return a cached credential only if it hasn't expired.
398         """
399         if (os.path.isfile(file)):
400             credential = Credential(filename=file)
401             # make sure it isnt expired 
402             if not credential.get_lifetime or \
403                datetime.datetime.today() < credential.get_lifetime():
404                 return credential
405         return None 
406  
407     def get_user_cred(self):
408         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
409         file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
410         return self.get_cred(file, 'user', self.user)
411
412     def get_auth_cred(self):
413         if not self.authority:
414             print "no authority specified. Use -a or set SF_AUTH"
415             sys.exit(-1)
416         file = os.path.join(self.options.sfi_dir, get_leaf("authority") + ".cred")
417         return self.get_cred(file, 'authority', self.authority)
418
419     def get_slice_cred(self, name):
420         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
421         return self.get_cred(file, 'slice', name)
422  
423     def get_cred(self, file, type, hrn):
424         # attempt to load a cached credential 
425         cred = self.get_cached_credential(file)    
426         if not cred:
427             if type in ['user']:
428                 cert_string = self.cert.save_to_string(save_parents=True)
429                 user_name = self.user.replace(self.authority + ".", '')
430                 if user_name.count(".") > 0:
431                     user_name = user_name.replace(".", '_')
432                     self.user = self.authority + "." + user_name
433                 cred_str = self.registry.get_self_credential(cert_string, "user", hrn)
434             else:
435                 # bootstrap slice credential from user credential
436                 user_cred = self.get_user_cred().save_to_string(save_parents=True)
437                 cred_str = self.registry.get_credential(user_cred, type, hrn)
438             
439             if not cred_str:
440                 print "Failed to get %s credential" % (type)
441                 sys.exit(-1)
442                 
443             cred = Credential(string=cred_str)
444             cred.save_to_file(file, save_parents=True)
445             if self.options.verbose:
446                 print "Writing %s credential to %s" %(type, file)
447
448         return cred
449  
450     
451     def get_rspec_file(self, rspec):
452        if (os.path.isabs(rspec)):
453           file = rspec
454        else:
455           file = os.path.join(self.options.sfi_dir, rspec)
456        if (os.path.isfile(file)):
457           return file
458        else:
459           print "No such rspec file", rspec
460           sys.exit(1)
461     
462     def get_record_file(self, record):
463        if (os.path.isabs(record)):
464           file = record
465        else:
466           file = os.path.join(self.options.sfi_dir, record)
467        if (os.path.isfile(file)):
468           return file
469        else:
470           print "No such registry record file", record
471           sys.exit(1)
472     
473     def load_publickey_string(self, fn):
474        f = file(fn, "r")
475        key_string = f.read()
476     
477        # if the filename is a private key file, then extract the public key
478        if "PRIVATE KEY" in key_string:
479            outfn = tempfile.mktemp()
480            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
481            os.system(cmd)
482            f = file(outfn, "r")
483            key_string = f.read()
484            os.remove(outfn)
485     
486        return key_string
487
488     def get_component_server_from_hrn(self, hrn):
489         # direct connection to the nodes component manager interface
490         user_cred = self.get_user_cred().save_to_string(save_parents=True)
491         records = self.registry.Resolve(hrn, user_cred)
492         records = filter_records('node', records)
493         if not records:
494             print "No such component:", opts.component
495         record = records[0]
496   
497         return self.get_server(record['hostname'], CM_PORT, self.key_file, \
498                                self.cert_file, self.options)
499  
500     def get_server(self, host, port, keyfile, certfile):
501         """
502         Return an instnace of an xmlrpc server connection    
503         """
504         url = "http://%s:%s" % (host, port)
505         return xmlrpcprotocol.get_server(url, keyfile, certfile, self.options)
506
507     def get_server_from_opts(self, opts):
508         """
509         Return instance of an xmlrpc connection to a slice manager, aggregate
510         or component server depending on the specified opts
511         """
512         server = self.slicemgr
513         # direct connection to an aggregate
514         if hasattr(opts, 'aggregate') and opts.aggregate:
515             server = self.get_server(opts.aggregate, opts.port, self.key_file, self.cert_file)
516         # direct connection to the nodes component manager interface
517         if hasattr(opts, 'component') and opts.component:
518             server = self.get_component_server_from_hrn(opts.component)    
519  
520         return server
521     #==========================================================================
522     # Following functions implement the commands
523     #
524     # Registry-related commands
525     #==========================================================================
526   
527     def dispatch(self, command, cmd_opts, cmd_args):
528         getattr(self, command)(cmd_opts, cmd_args)
529  
530     # list entires in named authority registry
531     def list(self, opts, args):
532         user_cred = self.get_user_cred().save_to_string(save_parents=True)
533         hrn = args[0]
534         try:
535             list = self.registry.List(hrn, user_cred)
536         except IndexError:
537             raise Exception, "Not enough parameters for the 'list' command"
538           
539         # filter on person, slice, site, node, etc.  
540         # THis really should be in the self.filter_records funct def comment...
541         list = filter_records(opts.type, list)
542         for record in list:
543             print "%s (%s)" % (record['hrn'], record['type'])     
544         if opts.file:
545             file = opts.file
546             if not file.startswith(os.sep):
547                 file = os.path.join(self.options.sfi_dir, file)
548             save_records_to_file(file, list)
549         return
550     
551     # show named registry record
552     def show(self, opts, args):
553         user_cred = self.get_user_cred().save_to_string(save_parents=True)
554         hrn = args[0]
555         records = self.registry.Resolve(hrn, user_cred)
556         records = filter_records(opts.type, records)
557         if not records:
558             print "No record of type", opts.type
559         for record in records:
560             if record['type'] in ['user']:
561                 record = UserRecord(dict=record)
562             elif record['type'] in ['slice']:
563                 record = SliceRecord(dict=record)
564             elif record['type'] in ['node']:
565                 record = NodeRecord(dict=record)
566             elif record['type'] in ['authority', 'ma', 'sa']:
567                 record = AuthorityRecord(dict=record)
568             else:
569                 record = SfaRecord(dict=record)
570             if (opts.format == "text"): 
571                 record.dump()  
572             else:
573                 print record.save_to_string() 
574        
575         if opts.file:
576             file = opts.file
577             if not file.startswith(os.sep):
578                 file = os.path.join(self.options.sfi_dir, file)
579             save_records_to_file(file, records)
580         return
581     
582     def delegate(self, opts, args):
583
584         delegee_hrn = args[0]
585         if opts.delegate_user:
586             user_cred = self.get_user_cred()
587             cred = self.delegate_cred(user_cred, delegee_hrn)
588         elif opts.delegate_slice:
589             slice_cred = self.get_slice_cred(opts.delegate_slice)
590             cred = self.delegate_cred(slice_cred, delegee_hrn)
591         else:
592             print "Must specify either --user or --slice <hrn>"
593             return
594         delegated_cred = Credential(string=cred)
595         object_hrn = delegated_cred.get_gid_object().get_hrn()
596         if opts.delegate_user:
597             dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
598                                   + get_leaf(object_hrn) + ".cred")
599         elif opts.delegate_slice:
600             dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
601                                   + get_leaf(object_hrn) + ".cred")
602
603         delegated_cred.save_to_file(dest_fn, save_parents=True)
604
605         print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
606     
607     def delegate_cred(self, object_cred, hrn):
608         # the gid and hrn of the object we are delegating
609         if isinstance(object_cred, str):
610             object_cred = Credential(string=object_cred) 
611         object_gid = object_cred.get_gid_object()
612         object_hrn = object_gid.get_hrn()
613     
614         if not object_cred.get_privileges().get_all_delegate():
615             print "Error: Object credential", object_hrn, "does not have delegate bit set"
616             return
617
618         # the delegating user's gid
619         caller_gid = self._get_gid(self.user)
620         caller_gidfile = os.path.join(self.options.sfi_dir, self.user + ".gid")
621   
622         # the gid of the user who will be delegated to
623         delegee_gid = self._get_gid(hrn)
624         delegee_hrn = delegee_gid.get_hrn()
625         delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
626         delegee_gid.save_to_file(filename=delegee_gidfile)
627         dcred = object_cred.delegate(delegee_gidfile, self.get_key_file(), caller_gidfile)
628         return dcred.save_to_string(save_parents=True)
629      
630     # removed named registry record
631     #   - have to first retrieve the record to be removed
632     def remove(self, opts, args):
633         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
634         hrn = args[0]
635         type = opts.type 
636         if type in ['all']:
637             type = '*'
638         return self.registry.Remove(hrn, auth_cred, type)
639     
640     # add named registry record
641     def add(self, opts, args):
642         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
643         record_filepath = args[0]
644         rec_file = self.get_record_file(record_filepath)
645         record = load_record_from_file(rec_file).as_dict()
646         return self.registry.Register(record, auth_cred)
647     
648     # update named registry entry
649     def update(self, opts, args):
650         user_cred = self.get_user_cred()
651         rec_file = self.get_record_file(args[0])
652         record = load_record_from_file(rec_file)
653         if record['type'] == "user":
654             if record.get_name() == user_cred.get_gid_object().get_hrn():
655                 cred = user_cred.save_to_string(save_parents=True)
656             else:
657                 cred = self.get_auth_cred().save_to_string(save_parents=True)
658         elif record['type'] in ["slice"]:
659             try:
660                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
661             except ServerException, e:
662                # XXX smbaker -- once we have better error return codes, update this
663                # to do something better than a string compare
664                if "Permission error" in e.args[0]:
665                    cred = self.get_auth_cred().save_to_string(save_parents=True)
666                else:
667                    raise
668         elif record.get_type() in ["authority"]:
669             cred = self.get_auth_cred().save_to_string(save_parents=True)
670         elif record.get_type() == 'node':
671             cred = self.get_auth_cred().save_to_string(save_parents=True)
672         else:
673             raise "unknown record type" + record.get_type()
674         record = record.as_dict()
675         return self.registry.Update(record, cred)
676   
677     def get_trusted_certs(self, opts, args):
678         """
679         return uhe trusted certs at this interface 
680         """ 
681         trusted_certs = self.registry.get_trusted_certs()
682         for trusted_cert in trusted_certs:
683             cert = Certificate(string=trusted_cert)
684             print cert.get_subject()
685         return 
686
687     def aggregates(self, opts, args):
688         """
689         return a list of details about known aggregates
690         """
691         user_cred = self.get_user_cred().save_to_string(save_parents=True)
692         hrn = None
693         if args:
694             hrn = args[0]
695
696         result = self.registry.get_aggregates(user_cred, hrn)
697         display_list(result)
698         return 
699
700     def registries(self, opts, args):
701         """
702         return a list of details about known registries
703         """
704         user_cred = self.get_user_cred().save_to_string(save_parents=True)
705         hrn = None
706         if args:
707             hrn = args[0]
708         result = self.registry.get_registries(user_cred, hrn)
709         display_list(result)
710         return
711
712  
713     # ==================================================================
714     # Slice-related commands
715     # ==================================================================
716     
717
718     def version(self, opts, args):
719         server = self.get_server_from_opts(opts)
720         
721         print server.GetVersion()
722
723     # list instantiated slices
724     def slices(self, opts, args):
725         """
726         list instantiated slices
727         """
728         user_cred = self.get_user_cred().save_to_string(save_parents=True)
729         creds = [user_cred]
730         if opts.delegate:
731             delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority))
732             creds.append(delegated_cred)  
733         server = self.get_server_from_opts(opts)
734         results = server.ListSlices(creds)
735         display_list(results)
736         return
737     
738     # show rspec for named slice
739     def resources(self, opts, args):
740         user_cred = self.get_user_cred().save_to_string(save_parents=True)
741         server = self.slicemgr
742         call_options = {}
743         server = self.get_server_from_opts(opts)
744         
745         if args:
746             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
747             hrn = args[0]
748             call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
749         else:
750             cred = user_cred
751             hrn = None
752      
753         creds = [cred]
754         if opts.delegate:
755             delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
756             creds.append(delegated_cred) 
757         result = server.ListResources(creds, call_options)
758         format = opts.format
759         display_rspec(result, format)
760         if (opts.file is not None):
761             file = opts.file
762             if not file.startswith(os.sep):
763                 file = os.path.join(self.options.sfi_dir, file)
764             save_rspec_to_file(result, file)
765         return
766     
767     # created named slice with given rspec
768     def create(self, opts, args):
769         slice_hrn = args[0]
770         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
771         user_cred = self.get_user_cred()
772         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
773         creds = [slice_cred]
774         if opts.delegate:
775             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
776             creds.append(delegated_cred)
777         rspec_file = self.get_rspec_file(args[1])
778         rspec = open(rspec_file).read()
779         server = self.get_server_from_opts(opts)
780         result =  server.CreateSliver(slice_urn, creds, rspec, [])
781         print result
782         return result
783
784     # get a ticket for the specified slice
785     def get_ticket(self, opts, args):
786         slice_hrn, rspec_path = args[0], args[1]
787         slice_urn = hrn_to_urn(slice_hrn, 'slice')
788         user_cred = self.get_user_cred()
789         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
790         creds = [slice_cred]
791         if opts.delegate:
792             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
793             creds.append(delegated_cred)
794         rspec_file = self.get_rspec_file(rspec_path) 
795         rspec = open(rspec_file).read()
796         server = self.get_server_from_opts(opts)
797         ticket_string = server.GetTicket(slice_urn, creds, rspec, [])
798         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
799         print "writing ticket to ", file        
800         ticket = SfaTicket(string=ticket_string)
801         ticket.save_to_file(filename=file, save_parents=True)
802
803     def redeem_ticket(self, opts, args):
804         ticket_file = args[0]
805         
806         # get slice hrn from the ticket
807         # use this to get the right slice credential 
808         ticket = SfaTicket(filename=ticket_file)
809         ticket.decode()
810         slice_hrn = ticket.gidObject.get_hrn()
811         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
812         #slice_hrn = ticket.attributes['slivers'][0]['hrn']
813         user_cred = self.get_user_cred()
814         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
815         
816         # get a list of node hostnames from the RSpec 
817         tree = etree.parse(StringIO(ticket.rspec))
818         root = tree.getroot()
819         hostnames = root.xpath("./network/site/node/hostname/text()")
820         
821         # create an xmlrpc connection to the component manager at each of these
822         # components and gall redeem_ticket
823         connections = {}
824         for hostname in hostnames:
825             try:
826                 print "Calling redeem_ticket at %(hostname)s " % locals(),
827                 server = self.get_server(hostname, CM_PORT, self.key_file, \
828                                          self.cert_file, self.options.debug)
829                 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
830                 print "Success"
831             except socket.gaierror:
832                 print "Failed:",
833                 print "Componet Manager not accepting requests" 
834             except Exception, e:
835                 print "Failed:", e.message
836         return
837  
838     # delete named slice
839     def delete(self, opts, args):
840         slice_hrn = args[0]
841         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
842         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
843         creds = [slice_cred]
844         if opts.delegate:
845             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
846             creds.append(delegated_cred)
847         server = self.get_server_from_opts(opts)
848         return server.DeleteSliver(slice_urn, creds)
849     
850     # start named slice
851     def start(self, opts, args):
852         slice_hrn = args[0]
853         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
854         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
855         creds = [slice_cred]
856         if opts.delegate:
857             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
858             creds.append(delegated_cred)
859         server = self.get_server_from_opts(opts)
860         return server.Start(slice_urn, creds)
861     
862     # stop named slice
863     def stop(self, opts, args):
864         slice_hrn = args[0]
865         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
866         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
867         creds = [slice_cred]
868         if opts.delegate:
869             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
870             creds.append(delegated_cred)
871         server = self.get_server_from_opts(opts)
872         return server.Stop(slice_urn, creds)
873     
874     # reset named slice
875     def reset(self, opts, args):
876         slice_hrn = args[0]
877         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
878         server = self.get_server_from_opts(opts)
879         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
880         creds = [slice_cred]
881         if opts.delegate:
882             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
883             creds.append(delegated_cred)
884         return server.reset_slice(creds, slice_urn)
885
886     def renew(self, opts, args):
887         slice_hrn = args[0]
888         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
889         server = self.get_server_from_opts(opts)
890         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
891         creds = [slice_cred]
892         if opts.delegate:
893             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
894             creds.append(delegated_cred)
895         time = args[1]
896         return server.RenewSliver(slice_urn, creds, time)
897
898
899     def status(self, opts, args):
900         slice_hrn = args[0]
901         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
902         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
903         creds = [slice_cred]
904         if opts.delegate:
905             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
906             creds.append(delegated_cred)
907         server = self.get_server_from_opts(opts)
908         print server.SliverStatus(slice_urn, creds)
909
910
911     def shutdown(self, opts, args):
912         slice_hrn = args[0]
913         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
914         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
915         creds = [slice_cred]
916         if opts.delegate:
917             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
918             creds.append(delegated_cred)
919         server = self.get_server_from_opts(opts)
920         return server.Shutdown(slice_urn, creds)         
921     
922     #
923     # Main: parse arguments and dispatch to command
924     #
925     def main(self):
926         parser = self.create_parser()
927         (options, args) = parser.parse_args()
928         self.options = options
929    
930         if options.hashrequest:
931             self.hashrequest = True
932  
933         if len(args) <= 0:
934             print "No command given. Use -h for help."
935             return - 1
936     
937         command = args[0]
938         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
939         if self.options.verbose :
940             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
941                                                                    options.sfi_dir, options.user,
942                                                                    options.auth)
943             print "Command %s" % command
944             if command in ("resources"):
945                 print "resources cmd_opts %s" % cmd_opts.format
946             elif command in ("list", "show", "remove"):
947                 print "cmd_opts.type %s" % cmd_opts.type
948             print "cmd_args %s" % cmd_args
949     
950         self.set_servers()
951     
952         try:
953             self.dispatch(command, cmd_opts, cmd_args)
954         except KeyError:
955             raise 
956             print "Command not found:", command
957             sys.exit(1)
958     
959         return
960     
961 if __name__ == "__main__":
962    Sfi().main()