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