ffc2dc5c54f9a28fe0313755640d76c79caf0819
[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        if self.options.verbose :
304           print "Contacting Slice Manager at:", sm_url
305           print "Contacting Registry at:", reg_url
306     
307        # Get key and certificate
308        key_file = self.get_key_file()
309        cert_file = self.get_cert_file(key_file)
310        self.key = Keypair(filename=key_file) 
311        self.key_file = key_file
312        self.cert_file = cert_file
313        self.cert = Certificate(filename=cert_file) 
314        # Establish connection to server(s)
315        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file, self.options.debug)  
316        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file, self.options.debug)
317
318        return
319     
320     #
321     # Get various credential and spec files
322     #
323     # Establishes limiting conventions
324     #   - conflates MAs and SAs
325     #   - assumes last token in slice name is unique
326     #
327     # Bootstraps credentials
328     #   - bootstrap user credential from self-signed certificate
329     #   - bootstrap authority credential from user credential
330     #   - bootstrap slice credential from user credential
331     #
332     
333     
334     def get_key_file(self):
335        file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
336        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
337        if (os.path.isfile(file)):
338           return file
339        else:
340           print "Key file", file, "does not exist"
341           sys.exit(-1)
342        return
343     
344     def get_cert_file(self, key_file):
345     
346        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
347        file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
348        if (os.path.isfile(file)):
349           return file
350        else:
351           k = Keypair(filename=key_file)
352           cert = Certificate(subject=self.user)
353           cert.set_pubkey(k)
354           cert.set_issuer(k, self.user)
355           cert.sign()
356           if self.options.verbose :
357              print "Writing self-signed certificate to", file
358           cert.save_to_file(file)
359           return file
360
361     def get_cached_gid(self, file):
362         """
363         Return a cached gid    
364         """
365         gid = None 
366         if (os.path.isfile(file)):
367             gid = GID(filename=file)
368         return gid
369
370     def get_gid(self, opts, args):
371         hrn = None
372         if args:
373             hrn = args[0]
374         gid = self._get_gid(hrn)
375         print gid.save_to_string(save_parents=True)
376         return gid
377
378     def _get_gid(self, hrn=None):
379         if not hrn:
380             hrn = self.user
381  
382         gidfile = os.path.join(self.options.sfi_dir, hrn + ".gid")
383         gid = self.get_cached_gid(gidfile)
384         if not gid:
385             user_cred = self.get_user_cred()
386             records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
387             if not records:
388                 raise RecordNotFound(args[0])
389             gid = GID(string=records[0]['gid'])
390             if self.options.verbose:
391                 print "Writing gid to ", gidfile 
392             gid.save_to_file(filename=gidfile)
393         return gid   
394                 
395      
396     def get_cached_credential(self, file):
397         """
398         Return a cached credential only if it hasn't expired.
399         """
400         if (os.path.isfile(file)):
401             credential = Credential(filename=file)
402             # make sure it isnt expired 
403             if not credential.get_lifetime or \
404                datetime.datetime.today() < credential.get_lifetime():
405                 return credential
406         return None 
407  
408     def get_user_cred(self):
409         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
410         file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
411         return self.get_cred(file, 'user', self.user)
412
413     def get_auth_cred(self):
414         if not self.authority:
415             print "no authority specified. Use -a or set SF_AUTH"
416             sys.exit(-1)
417         file = os.path.join(self.options.sfi_dir, get_leaf("authority") + ".cred")
418         return self.get_cred(file, 'authority', self.authority)
419
420     def get_slice_cred(self, name):
421         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
422         return self.get_cred(file, 'slice', name)
423  
424     def get_cred(self, file, type, hrn):
425         # attempt to load a cached credential 
426         cred = self.get_cached_credential(file)    
427         if not cred:
428             if type in ['user']:
429                 cert_string = self.cert.save_to_string(save_parents=True)
430                 user_name = self.user.replace(self.authority + ".", '')
431                 if user_name.count(".") > 0:
432                     user_name = user_name.replace(".", '_')
433                     self.user = self.authority + "." + user_name
434                 cred_str = self.registry.get_self_credential(cert_string, "user", hrn)
435             else:
436                 # bootstrap slice credential from user credential
437                 user_cred = self.get_user_cred().save_to_string(save_parents=True)
438                 cred_str = self.registry.get_credential(user_cred, type, hrn)
439             
440             if not cred_str:
441                 print "Failed to get %s credential" % (type)
442                 sys.exit(-1)
443                 
444             cred = Credential(string=cred_str)
445             cred.save_to_file(file, save_parents=True)
446             if self.options.verbose:
447                 print "Writing %s credential to %s" %(type, file)
448
449         return cred
450  
451     
452     def get_rspec_file(self, rspec):
453        if (os.path.isabs(rspec)):
454           file = rspec
455        else:
456           file = os.path.join(self.options.sfi_dir, rspec)
457        if (os.path.isfile(file)):
458           return file
459        else:
460           print "No such rspec file", rspec
461           sys.exit(1)
462     
463     def get_record_file(self, record):
464        if (os.path.isabs(record)):
465           file = record
466        else:
467           file = os.path.join(self.options.sfi_dir, record)
468        if (os.path.isfile(file)):
469           return file
470        else:
471           print "No such registry record file", record
472           sys.exit(1)
473     
474     def load_publickey_string(self, fn):
475        f = file(fn, "r")
476        key_string = f.read()
477     
478        # if the filename is a private key file, then extract the public key
479        if "PRIVATE KEY" in key_string:
480            outfn = tempfile.mktemp()
481            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
482            os.system(cmd)
483            f = file(outfn, "r")
484            key_string = f.read()
485            os.remove(outfn)
486     
487        return key_string
488
489     def get_component_server_from_hrn(self, hrn):
490         # direct connection to the nodes component manager interface
491         user_cred = self.get_user_cred().save_to_string(save_parents=True)
492         records = self.registry.Resolve(hrn, user_cred)
493         records = filter_records('node', records)
494         if not records:
495             print "No such component:", opts.component
496         record = records[0]
497   
498         return self.get_server(record['hostname'], CM_PORT, self.key_file, \
499                                self.cert_file, self.options.debug)
500  
501     def get_server(self, host, port, keyfile, certfile, debug):
502         """
503         Return an instnace of an xmlrpc server connection    
504         """
505         url = "http://%s:%s" % (host, port)
506         return xmlrpcprotocol.get_server(url, keyfile, certfile, debug)
507
508     def get_server_from_opts(self, opts):
509         """
510         Return instance of an xmlrpc connection to a slice manager, aggregate
511         or component server depending on the specified opts
512         """
513         server = self.slicemgr
514         # direct connection to an aggregate
515         if hasattr(opts, 'aggregate') and opts.aggregate:
516             server = self.get_server(opts.aggregate, opts.port, self.key_file, \
517                                      self.cert_file, self.options.debug)
518         # direct connection to the nodes component manager interface
519         if hasattr(opts, 'component') and opts.component:
520             server = self.get_component_server_from_hrn(opts.component)    
521  
522         return server
523     #==========================================================================
524     # Following functions implement the commands
525     #
526     # Registry-related commands
527     #==========================================================================
528   
529     def dispatch(self, command, cmd_opts, cmd_args):
530         getattr(self, command)(cmd_opts, cmd_args)
531  
532     # list entires in named authority registry
533     def list(self, opts, args):
534         user_cred = self.get_user_cred().save_to_string(save_parents=True)
535         hrn = args[0]
536         try:
537             list = self.registry.List(hrn, user_cred)
538         except IndexError:
539             raise Exception, "Not enough parameters for the 'list' command"
540           
541         # filter on person, slice, site, node, etc.  
542         # THis really should be in the self.filter_records funct def comment...
543         list = filter_records(opts.type, list)
544         for record in list:
545             print "%s (%s)" % (record['hrn'], record['type'])     
546         if opts.file:
547             file = opts.file
548             if not file.startswith(os.sep):
549                 file = os.path.join(self.options.sfi_dir, file)
550             save_records_to_file(file, list)
551         return
552     
553     # show named registry record
554     def show(self, opts, args):
555         user_cred = self.get_user_cred().save_to_string(save_parents=True)
556         hrn = args[0]
557         records = self.registry.Resolve(hrn, user_cred)
558         records = filter_records(opts.type, records)
559         if not records:
560             print "No record of type", opts.type
561         for record in records:
562             if record['type'] in ['user']:
563                 record = UserRecord(dict=record)
564             elif record['type'] in ['slice']:
565                 record = SliceRecord(dict=record)
566             elif record['type'] in ['node']:
567                 record = NodeRecord(dict=record)
568             elif record['type'] in ['authority', 'ma', 'sa']:
569                 record = AuthorityRecord(dict=record)
570             else:
571                 record = SfaRecord(dict=record)
572             if (opts.format == "text"): 
573                 record.dump()  
574             else:
575                 print record.save_to_string() 
576        
577         if opts.file:
578             file = opts.file
579             if not file.startswith(os.sep):
580                 file = os.path.join(self.options.sfi_dir, file)
581             save_records_to_file(file, records)
582         return
583     
584     def delegate(self, opts, args):
585
586         delegee_hrn = args[0]
587         if opts.delegate_user:
588             user_cred = self.get_user_cred()
589             cred = self.delegate_cred(user_cred, delegee_hrn)
590         elif opts.delegate_slice:
591             slice_cred = self.get_slice_cred(opts.delegate_slice)
592             cred = self.delegate_cred(slice_cred, delegee_hrn)
593         else:
594             print "Must specify either --user or --slice <hrn>"
595             return
596         delegated_cred = Credential(string=cred)
597         object_hrn = delegated_cred.get_gid_object().get_hrn()
598         if opts.delegate_user:
599             dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
600                                   + get_leaf(object_hrn) + ".cred")
601         elif opts.delegate_slice:
602             dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
603                                   + get_leaf(object_hrn) + ".cred")
604
605         delegated_cred.save_to_file(dest_fn, save_parents=True)
606
607         print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
608     
609     def delegate_cred(self, object_cred, hrn):
610         # the gid and hrn of the object we are delegating
611         if isinstance(object_cred, str):
612             object_cred = Credential(string=object_cred) 
613         object_gid = object_cred.get_gid_object()
614         object_hrn = object_gid.get_hrn()
615     
616         if not object_cred.get_privileges().get_all_delegate():
617             print "Error: Object credential", object_hrn, "does not have delegate bit set"
618             return
619
620         # the delegating user's gid
621         caller_gid = self._get_gid(self.user)
622         caller_gidfile = os.path.join(self.options.sfi_dir, self.user + ".gid")
623   
624         # the gid of the user who will be delegated to
625         delegee_gid = self._get_gid(hrn)
626         delegee_hrn = delegee_gid.get_hrn()
627         delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
628         delegee_gid.save_to_file(filename=delegee_gidfile)
629         dcred = object_cred.delegate(delegee_gidfile, self.get_key_file(), caller_gidfile)
630         return dcred.save_to_string(save_parents=True)
631      
632     # removed named registry record
633     #   - have to first retrieve the record to be removed
634     def remove(self, opts, args):
635         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
636         hrn = args[0]
637         type = opts.type 
638         if type in ['all']:
639             type = '*'
640         return self.registry.Remove(hrn, auth_cred, type)
641     
642     # add named registry record
643     def add(self, opts, args):
644         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
645         record_filepath = args[0]
646         rec_file = self.get_record_file(record_filepath)
647         record = load_record_from_file(rec_file).as_dict()
648         return self.registry.Register(record, auth_cred)
649     
650     # update named registry entry
651     def update(self, opts, args):
652         user_cred = self.get_user_cred()
653         rec_file = self.get_record_file(args[0])
654         record = load_record_from_file(rec_file)
655         if record['type'] == "user":
656             if record.get_name() == user_cred.get_gid_object().get_hrn():
657                 cred = user_cred.save_to_string(save_parents=True)
658             else:
659                 cred = self.get_auth_cred().save_to_string(save_parents=True)
660         elif record['type'] in ["slice"]:
661             try:
662                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
663             except ServerException, e:
664                # XXX smbaker -- once we have better error return codes, update this
665                # to do something better than a string compare
666                if "Permission error" in e.args[0]:
667                    cred = self.get_auth_cred().save_to_string(save_parents=True)
668                else:
669                    raise
670         elif record.get_type() in ["authority"]:
671             cred = self.get_auth_cred().save_to_string(save_parents=True)
672         elif record.get_type() == 'node':
673             cred = self.get_auth_cred().save_to_string(save_parents=True)
674         else:
675             raise "unknown record type" + record.get_type()
676         record = record.as_dict()
677         return self.registry.Update(record, cred)
678   
679     def get_trusted_certs(self, opts, args):
680         """
681         return uhe trusted certs at this interface 
682         """ 
683         trusted_certs = self.registry.get_trusted_certs()
684         for trusted_cert in trusted_certs:
685             cert = Certificate(string=trusted_cert)
686             print cert.get_subject()
687         return 
688
689     def aggregates(self, opts, args):
690         """
691         return a list of details about known aggregates
692         """
693         user_cred = self.get_user_cred().save_to_string(save_parents=True)
694         hrn = None
695         if args:
696             hrn = args[0]
697
698         result = self.registry.get_aggregates(user_cred, hrn)
699         display_list(result)
700         return 
701
702     def registries(self, opts, args):
703         """
704         return a list of details about known registries
705         """
706         user_cred = self.get_user_cred().save_to_string(save_parents=True)
707         hrn = None
708         if args:
709             hrn = args[0]
710         result = self.registry.get_registries(user_cred, hrn)
711         display_list(result)
712         return
713
714  
715     # ==================================================================
716     # Slice-related commands
717     # ==================================================================
718     
719
720     def version(self, opts, args):
721         server = self.get_server_from_opts(opts)
722         
723         print server.GetVersion()
724
725     # list instantiated slices
726     def slices(self, opts, args):
727         """
728         list instantiated slices
729         """
730         user_cred = self.get_user_cred().save_to_string(save_parents=True)
731         creds = [user_cred]
732         if opts.delegate:
733             delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority))
734             creds.append(delegated_cred)  
735         server = self.get_server_from_opts(opts)
736         results = server.ListSlices(creds)
737         display_list(results)
738         return
739     
740     # show rspec for named slice
741     def resources(self, opts, args):
742         user_cred = self.get_user_cred().save_to_string(save_parents=True)
743         server = self.slicemgr
744         call_options = {}
745         server = self.get_server_from_opts(opts)
746         
747         if args:
748             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
749             hrn = args[0]
750             call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
751         else:
752             cred = user_cred
753             hrn = None
754      
755         creds = [cred]
756         if opts.delegate:
757             delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
758             creds.append(delegated_cred) 
759         result = server.ListResources(creds, call_options)
760         format = opts.format
761         display_rspec(result, format)
762         if (opts.file is not None):
763             file = opts.file
764             if not file.startswith(os.sep):
765                 file = os.path.join(self.options.sfi_dir, file)
766             save_rspec_to_file(result, file)
767         return
768     
769     # created named slice with given rspec
770     def create(self, opts, args):
771         slice_hrn = args[0]
772         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
773         user_cred = self.get_user_cred()
774         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
775         creds = [slice_cred]
776         if opts.delegate:
777             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
778             creds.append(delegated_cred)
779         rspec_file = self.get_rspec_file(args[1])
780         rspec = open(rspec_file).read()
781         server = self.get_server_from_opts(opts)
782         result =  server.CreateSliver(slice_urn, creds, rspec, [])
783         print result
784         return result
785
786     # get a ticket for the specified slice
787     def get_ticket(self, opts, args):
788         slice_hrn, rspec_path = args[0], args[1]
789         slice_urn = hrn_to_urn(slice_hrn, 'slice')
790         user_cred = self.get_user_cred()
791         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
792         creds = [slice_cred]
793         if opts.delegate:
794             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
795             creds.append(delegated_cred)
796         rspec_file = self.get_rspec_file(rspec_path) 
797         rspec = open(rspec_file).read()
798         server = self.get_server_from_opts(opts)
799         ticket_string = server.GetTicket(slice_urn, creds, rspec, [])
800         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
801         print "writing ticket to ", file        
802         ticket = SfaTicket(string=ticket_string)
803         ticket.save_to_file(filename=file, save_parents=True)
804
805     def redeem_ticket(self, opts, args):
806         ticket_file = args[0]
807         
808         # get slice hrn from the ticket
809         # use this to get the right slice credential 
810         ticket = SfaTicket(filename=ticket_file)
811         ticket.decode()
812         slice_hrn = ticket.gidObject.get_hrn()
813         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
814         #slice_hrn = ticket.attributes['slivers'][0]['hrn']
815         user_cred = self.get_user_cred()
816         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
817         
818         # get a list of node hostnames from the RSpec 
819         tree = etree.parse(StringIO(ticket.rspec))
820         root = tree.getroot()
821         hostnames = root.xpath("./network/site/node/hostname/text()")
822         
823         # create an xmlrpc connection to the component manager at each of these
824         # components and gall redeem_ticket
825         connections = {}
826         for hostname in hostnames:
827             try:
828                 print "Calling redeem_ticket at %(hostname)s " % locals(),
829                 server = self.get_server(hostname, CM_PORT, self.key_file, \
830                                          self.cert_file, self.options.debug)
831                 server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
832                 print "Success"
833             except socket.gaierror:
834                 print "Failed:",
835                 print "Componet Manager not accepting requests" 
836             except Exception, e:
837                 print "Failed:", e.message
838         return
839  
840     # delete named slice
841     def delete(self, opts, args):
842         slice_hrn = args[0]
843         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
844         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
845         creds = [slice_cred]
846         if opts.delegate:
847             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
848             creds.append(delegated_cred)
849         server = self.get_server_from_opts(opts)
850         return server.DeleteSliver(slice_urn, creds)
851     
852     # start named slice
853     def start(self, opts, args):
854         slice_hrn = args[0]
855         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
856         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
857         creds = [slice_cred]
858         if opts.delegate:
859             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
860             creds.append(delegated_cred)
861         server = self.get_server_from_opts(opts)
862         return server.Start(slice_urn, creds)
863     
864     # stop named slice
865     def stop(self, opts, args):
866         slice_hrn = args[0]
867         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
868         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
869         creds = [slice_cred]
870         if opts.delegate:
871             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
872             creds.append(delegated_cred)
873         server = self.get_server_from_opts(opts)
874         return server.Stop(slice_urn, creds)
875     
876     # reset named slice
877     def reset(self, opts, args):
878         slice_hrn = args[0]
879         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
880         server = self.get_server_from_opts(opts)
881         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
882         creds = [slice_cred]
883         if opts.delegate:
884             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
885             creds.append(delegated_cred)
886         return server.reset_slice(creds, slice_urn)
887
888     def renew(self, opts, args):
889         slice_hrn = args[0]
890         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
891         server = self.get_server_from_opts(opts)
892         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
893         creds = [slice_cred]
894         if opts.delegate:
895             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
896             creds.append(delegated_cred)
897         time = args[1]
898         return server.RenewSliver(slice_urn, creds, time)
899
900
901     def status(self, opts, args):
902         slice_hrn = args[0]
903         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
904         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
905         creds = [slice_cred]
906         if opts.delegate:
907             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
908             creds.append(delegated_cred)
909         server = self.get_server_from_opts(opts)
910         print server.SliverStatus(slice_urn, creds)
911
912
913     def shutdown(self, opts, args):
914         slice_hrn = args[0]
915         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
916         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
917         creds = [slice_cred]
918         if opts.delegate:
919             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
920             creds.append(delegated_cred)
921         server = self.get_server_from_opts(opts)
922         return server.Shutdown(slice_urn, creds)         
923     
924     #
925     # Main: parse arguments and dispatch to command
926     #
927     def main(self):
928         parser = self.create_parser()
929         (options, args) = parser.parse_args()
930         self.options = options
931    
932         if options.hashrequest:
933             self.hashrequest = True
934  
935         if len(args) <= 0:
936             print "No command given. Use -h for help."
937             return - 1
938     
939         command = args[0]
940         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
941         if self.options.verbose :
942             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
943                                                                    options.sfi_dir, options.user,
944                                                                    options.auth)
945             print "Command %s" % command
946             if command in ("resources"):
947                 print "resources cmd_opts %s" % cmd_opts.format
948             elif command in ("list", "show", "remove"):
949                 print "cmd_opts.type %s" % cmd_opts.type
950             print "cmd_args %s" % cmd_args
951     
952         self.set_servers()
953     
954         try:
955             self.dispatch(command, cmd_opts, cmd_args)
956         except KeyError:
957             raise 
958             print "Command not found:", command
959             sys.exit(1)
960     
961         return
962     
963 if __name__ == "__main__":
964    Sfi().main()