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