add --debug option to see xml-rpc dialog.
[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 from types import StringTypes, ListType
12 from optparse import OptionParser
13 from sfa.trust.certificate import Keypair, Certificate
14 from sfa.trust.credential import Credential
15 from sfa.util.sfaticket import SfaTicket
16 from sfa.util.record import *
17 from sfa.util.namespace import *
18 from sfa.util.rspec import RSpec
19 from sfa.util.xmlrpcprotocol import ServerException
20 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
21 from sfa.util.config import Config
22
23 # utility methods here
24 # display methods
25 def display_rspec(rspec, format = 'rspec'):
26     if format in ['dns']:
27         spec = RSpec()
28         spec.parseString(rspec)
29         hostnames = []
30         nodespecs = spec.getDictsByTagName('NodeSpec')
31         for nodespec in nodespecs:
32             if nodespec.has_key('name') and nodespec['name']:
33                 if isinstance(nodespec['name'], ListType):
34                     hostnames.extend(nodespec['name'])
35                 elif isinstance(nodespec['name'], StringTypes):
36                      hostnames.append(nodespec['name'])
37         result = hostnames
38     elif format in ['ip']:
39         spec = RSpec()
40         spec.parseString(rspec)
41         ips = []
42         ifspecs = spec.getDictsByTagName('IfSpec')
43         for ifspec in ifspecs:
44             if ifspec.has_key('addr') and ifspec['addr']:
45                 ips.append(ifspec['addr'])
46         result = ips
47     else:
48         result = rspec
49
50     print result
51     return
52
53 def display_list(results):
54     for result in results:
55         print result
56
57
58 def display_records(recordList, dump = False):
59     ''' Print all fields in the record'''
60     for record in recordList:
61         display_record(record, dump)
62
63 def display_record(record, dump = False):
64     if dump:
65         record.dump()
66     else:
67         info = record.getdict()
68         print "%s (%s)" % (info['hrn'], info['type'])
69     return
70
71
72 def filter_records(type, records):
73     filtered_records = []
74     for record in records:
75         if (record['type'] == type) or (type == "all"):
76             filtered_records.append(record)
77     return filtered_records
78
79
80 # save methods
81 def save_rspec_to_file(rspec, filename):
82     if not filename.endswith(".rspec"):
83         filename = filename + ".rspec"
84
85     f = open(filename, 'w')
86     f.write(rspec)
87     f.close()
88     return
89
90 def save_records_to_file(filename, recordList):
91     index = 0
92     for record in recordList:
93         if index>0:
94             save_record_to_file(filename + "." + str(index), record)
95         else:
96             save_record_to_file(filename, record)
97         index = index + 1
98
99 def save_record_to_file(filename, record):
100     if record['type'] in ['user']:
101         record = UserRecord(dict = record)
102     elif record['type'] in ['slice']:
103         record = SliceRecord(dict = record)
104     elif record['type'] in ['node']:
105         record = NodeRecord(dict = record)
106     elif record['type'] in ['authority', 'ma', 'sa']:
107         record = AuthorityRecord(dict = record)
108     else:
109         record = SfaRecord(dict = record)
110     str = record.save_to_string()
111     file(filename, "w").write(str)
112     return
113
114
115 # load methods
116 def load_record_from_file(filename):
117     str = file(filename, "r").read()
118     record = SfaRecord(string=str)
119     return record
120
121
122
123 class Sfi:
124     
125     slicemgr = None
126     registry = None
127     user = None
128     authority = None
129     options = None
130     hashrequest = False
131    
132     def create_cmd_parser(self,command, additional_cmdargs = None):
133         cmdargs = {"gid": "",
134                   "list": "name",
135                   "show": "name",
136                   "remove": "name",
137                   "add": "record",
138                   "update": "record",
139                   "aggregates": "[name]",
140                   "registries": "[name]",
141                   "slices": "",
142                   "resources": "[name]",
143                   "create": "name rspec",
144                   "get_trusted_certs": "cred",
145                   "get_ticket": "name rspec",
146                   "redeem_ticket": "ticket",  
147                   "delete": "name",
148                   "reset": "name",
149                   "start": "name",
150                   "stop": "name",
151                   "delegate": "name"
152                  }
153
154         if additional_cmdargs:
155             cmdargs.update(additional_cmdargs)
156
157         if command not in cmdargs:
158             print "Invalid command\n"
159             print "Commands: ",
160             for key in cmdargs.keys():
161                 print key+",",
162             print ""
163             sys.exit(2)
164
165         parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
166                                      % (command, cmdargs[command]))
167
168         if command in ("resources"):
169             parser.add_option("-f", "--format", dest="format",type="choice",
170                              help="display format ([xml]|dns|ip)",default="xml",
171                              choices=("xml","dns","ip"))
172             parser.add_option("-a", "--aggregate", dest="aggregate",
173                              default=None, help="aggregate hrn")
174
175         if command in ("create", "get_ticket"):
176             parser.add_option("-a", "--aggregate", dest="aggregate",default=None,
177                              help="aggregate hrn")
178
179         if command in ("start", "stop", "reset", "delete", "slices"):
180             parser.add_option("-c", "--component", dest="component",default=None,
181                              help="component hrn")
182             
183         if command in ("list", "show", "remove"):
184             parser.add_option("-t", "--type", dest="type",type="choice",
185                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
186                             choices=("all","user","slice","sa","ma","node","aggregate"),
187                             default="all")
188
189         if command in ("resources", "show", "list"):
190            parser.add_option("-o", "--output", dest="file",
191                             help="output XML to file", metavar="FILE", default=None)
192         
193         if command in ("show", "list"):
194            parser.add_option("-f", "--format", dest="format", type="choice",
195                              help="display format ([text]|xml)",default="text",
196                              choices=("text","xml"))
197
198         if command in ("delegate"):
199            parser.add_option("-u", "--user",
200                             action="store_true", dest="delegate_user", default=False,
201                             help="delegate user credential")
202            parser.add_option("-s", "--slice", dest="delegate_slice",
203                             help="delegate slice credential", metavar="HRN", default=None)
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        # 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        return
312     
313     #
314     # Get various credential and spec files
315     #
316     # Establishes limiting conventions
317     #   - conflates MAs and SAs
318     #   - assumes last token in slice name is unique
319     #
320     # Bootstraps credentials
321     #   - bootstrap user credential from self-signed certificate
322     #   - bootstrap authority credential from user credential
323     #   - bootstrap slice credential from user credential
324     #
325     
326     
327     def get_key_file(self):
328        file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
329        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
330        if (os.path.isfile(file)):
331           return file
332        else:
333           print "Key file", file, "does not exist"
334           sys.exit(-1)
335        return
336     
337     def get_cert_file(self,key_file):
338     
339        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
340        file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
341        if (os.path.isfile(file)):
342           return file
343        else:
344           k = Keypair(filename = key_file)
345           cert = Certificate(subject=self.user)
346           cert.set_pubkey(k)
347           cert.set_issuer(k, self.user)
348           cert.sign()
349           if self.options.verbose :
350              print "Writing self-signed certificate to", file
351           cert.save_to_file(file)
352           return file
353    
354     def get_gid(self):
355         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".gid")
356         file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".gid")
357         if (os.path.isfile(file)):
358             gid = GID(filename=file)
359             return gid
360         else:
361             cert_str = self.cert.save_to_string(save_parents=True)
362             gid_str = self.registry.get_gid(cert_str, self.user, "user")
363             gid = GID(string=gid_str)
364             if self.options.verbose:
365                 print "Writing user gid to", file
366             gid.save_to_file(file, save_parents=True)
367             return gid       
368  
369     def get_user_cred(self):
370         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
371         file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
372         if (os.path.isfile(file)):
373             user_cred = Credential(filename=file)
374             return user_cred
375         else:
376             # bootstrap user credential
377             cert_string = self.cert.save_to_string(save_parents=True)
378             user_name=self.user.replace(self.authority+".", '')
379             if user_name.count(".") > 0:
380                 user_name = user_name.replace(".", '_')
381                 self.user=self.authority + "." + user_name
382
383             user_cred = self.registry.get_self_credential(cert_string, "user", self.user)
384             if user_cred:
385                cred = Credential(string=user_cred)
386                cred.save_to_file(file, save_parents=True)
387                if self.options.verbose:
388                     print "Writing user credential to", file
389                return cred
390             else:
391                print "Failed to get user credential"
392                sys.exit(-1)
393   
394     def get_auth_cred(self):
395         if not self.authority:
396             print "no authority specified. Use -a or set SF_AUTH"
397             sys.exit(-1)
398     
399         file = os.path.join(self.options.sfi_dir, get_leaf("authority") +".cred")
400         if (os.path.isfile(file)):
401             auth_cred = Credential(filename=file)
402             return auth_cred
403         else:
404             # bootstrap authority credential from user credential
405             user_cred = self.get_user_cred().save_to_string(save_parents=True)
406             auth_cred = self.registry.get_credential(user_cred, "authority", self.authority)
407             if auth_cred:
408                 cred = Credential(string=auth_cred)
409                 cred.save_to_file(file, save_parents=True)
410                 if self.options.verbose:
411                     print "Writing authority credential to", file
412                 return cred
413             else:
414                 print "Failed to get authority credential"
415                 sys.exit(-1)
416     
417     def get_slice_cred(self,name):
418         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
419         if (os.path.isfile(file)):
420             slice_cred = Credential(filename=file)
421             return slice_cred
422         else:
423             # bootstrap slice credential from user credential
424             user_cred = self.get_user_cred().save_to_string(save_parents=True)
425             arg_list = [user_cred, "slice", name]
426             slice_cred_str = self.registry.get_credential(user_cred, "slice", name)
427             if slice_cred_str:
428                 slice_cred = Credential(string=slice_cred_str)
429                 slice_cred.save_to_file(file, save_parents=True)
430                 if self.options.verbose:
431                     print "Writing slice credential to", file
432                 return slice_cred
433             else:
434                 print "Failed to get slice credential"
435                 sys.exit(-1)
436     
437     def delegate_cred(self,cred, hrn, type = 'authority'):
438         # the gid and hrn of the object we are delegating
439         user_cred = Credential(string=cred)
440         object_gid = user_cred.get_gid_object()
441         object_hrn = object_gid.get_hrn()
442         #cred.set_delegate(True)
443         #if not cred.get_delegate():
444         #    raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
445            
446     
447         records = self.registry.resolve(cred, hrn)
448         records = filter_records(type, records)
449         
450         if not records:
451             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
452     
453         # the gid of the user who will be delegated too
454         record = SfaRecord(dict=records[0])
455         delegee_gid = record.get_gid_object()
456         delegee_hrn = delegee_gid.get_hrn()
457         
458         # the key and hrn of the user who will be delegating
459         user_key = Keypair(filename = self.get_key_file())
460         user_hrn = user_cred.get_gid_caller().get_hrn()
461     
462         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
463         dcred.set_gid_caller(delegee_gid)
464         dcred.set_gid_object(object_gid)
465         dcred.set_privileges(user_cred.get_privileges())
466         dcred.set_delegate(True)
467         dcred.set_pubkey(object_gid.get_pubkey())
468         dcred.set_issuer(user_key, user_hrn)
469         dcred.set_parent(user_cred)
470         dcred.encode()
471         dcred.sign()
472     
473         return dcred.save_to_string(save_parents=True)
474     
475     def get_rspec_file(self,rspec):
476        if (os.path.isabs(rspec)):
477           file = rspec
478        else:
479           file = os.path.join(self.options.sfi_dir, rspec)
480        if (os.path.isfile(file)):
481           return file
482        else:
483           print "No such rspec file", rspec
484           sys.exit(1)
485     
486     def get_record_file(self,record):
487        if (os.path.isabs(record)):
488           file = record
489        else:
490           file = os.path.join(self.options.sfi_dir, record)
491        if (os.path.isfile(file)):
492           return file
493        else:
494           print "No such registry record file", record
495           sys.exit(1)
496     
497     def load_publickey_string(self,fn):
498        f = file(fn,"r")
499        key_string = f.read()
500     
501        # if the filename is a private key file, then extract the public key
502        if "PRIVATE KEY" in key_string:
503            outfn = tempfile.mktemp()
504            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
505            os.system(cmd)
506            f = file(outfn, "r")
507            key_string = f.read()
508            os.remove(outfn)
509     
510        return key_string
511
512     def get_component_server_from_hrn(self, hrn):
513         # direct connection to the nodes component manager interface
514         user_cred = self.get_user_cred().save_to_string(save_parents=True)
515         records = self.registry.resolve(user_cred, hrn)
516         records = filter_records('node', records)
517         if not records:
518             print "No such component:", opts.component
519         record = records[0]
520         cm_port = "12346"
521         url = "https://%s:%s" % (record['hostname'], cm_port)
522         return xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
523     
524     #
525     # Following functions implement the commands
526     #
527     # Registry-related commands
528     #
529   
530     def dispatch(self,command, cmd_opts, cmd_args):
531         getattr(self,command)(cmd_opts, cmd_args)
532  
533     def gid(self, opts, args):
534         gid = self.get_gid()
535         print "GID: %s" % (gid.save_to_string(save_parents=True))
536         return   
537  
538     # list entires in named authority registry
539     def list(self,opts, args):
540         user_cred = self.get_user_cred().save_to_string(save_parents=True)
541         hrn = args[0]
542         try:
543             list = self.registry.list(user_cred, hrn)
544         except IndexError:
545             raise Exception, "Not enough parameters for the 'list' command"
546           
547         # filter on person, slice, site, node, etc.  
548         # THis really should be in the self.filter_records funct def comment...
549         list = filter_records(opts.type, list)
550         for record in list:
551             print "%s (%s)" % (record['hrn'], record['type'])     
552         if opts.file:
553             file = opts.file
554             if not file.startswith(os.sep):
555                 file = os.path.join(self.options.sfi_dir, file)
556             save_records_to_file(file, list)
557         return
558     
559     # show named registry record
560     def show(self,opts, args):
561         user_cred = self.get_user_cred().save_to_string(save_parents=True)
562         hrn = args[0]
563         records = self.registry.resolve(user_cred, hrn)
564         records = filter_records(opts.type, records)
565         if not records:
566             print "No record of type", opts.type
567         for record in records:
568             if record['type'] in ['user']:
569                 record = UserRecord(dict = record)
570             elif record['type'] in ['slice']:
571                 record = SliceRecord(dict = record)
572             elif record['type'] in ['node']:
573                 record = NodeRecord(dict = record)
574             elif record['type'] in ['authority', 'ma', 'sa']:
575                 record = AuthorityRecord(dict = record)
576             else:
577                 record = SfaRecord(dict = record)
578             if (opts.format=="text"): 
579                 record.dump()  
580             else:
581                 print record.save_to_string() 
582        
583         if opts.file:
584             file = opts.file
585             if not file.startswith(os.sep):
586                 file = os.path.join(self.options.sfi_dir, file)
587             save_records_to_file(file, records)
588         return
589     
590     def delegate(self,opts, args):
591        user_cred = self.get_user_cred()
592        if opts.delegate_user:
593            object_cred = user_cred
594        elif opts.delegate_slice:
595            object_cred = self.get_slice_cred(opts.delegate_slice)
596        else:
597            print "Must specify either --user or --slice <hrn>"
598            return
599     
600        # the gid and hrn of the object we are delegating
601        object_gid = object_cred.get_gid_object()
602        object_hrn = object_gid.get_hrn()
603     
604        if not object_cred.get_delegate():
605            print "Error: Object credential", object_hrn, "does not have delegate bit set"
606            return
607     
608        records = self.registry.resolve(user_cred.save_to_string(save_parents=True), args[0])
609        records = filter_records("user", records)
610     
611        if not records:
612            print "Error: Didn't find a user record for", args[0]
613            return
614     
615        # the gid of the user who will be delegated too
616        delegee_gid = GID(string=records[0]['gid'])
617        delegee_hrn = delegee_gid.get_hrn()
618    
619        # the key and hrn of the user who will be delegating
620        user_key = Keypair(filename = self.get_key_file())
621        user_hrn = user_cred.get_gid_caller().get_hrn()
622        subject_string = "%s delegated to %s" % (object_hrn, delegee_hrn)
623        dcred = Credential(subject=subject_string)
624        dcred.set_gid_caller(delegee_gid)
625        dcred.set_gid_object(object_gid)
626        dcred.set_privileges(object_cred.get_privileges())
627        dcred.set_delegate(True)
628        dcred.set_pubkey(object_gid.get_pubkey())
629        dcred.set_issuer(user_key, user_hrn)
630        dcred.set_parent(object_cred)
631        dcred.encode()
632        dcred.sign()
633     
634        if opts.delegate_user:
635            dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_" 
636                                   + get_leaf(object_hrn) + ".cred")
637        elif opts.delegate_slice:
638            dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_" 
639                                   + get_leaf(object_hrn) + ".cred")
640     
641        dcred.save_to_file(dest_fn, save_parents = True)
642     
643        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
644     
645     # removed named registry record
646     #   - have to first retrieve the record to be removed
647     def remove(self,opts, args):
648         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
649         hrn = args[0]
650         type = opts.type 
651         if type in ['all']:
652             type = '*'
653         return self.registry.remove(auth_cred, type, hrn)
654     
655     # add named registry record
656     def add(self,opts, args):
657         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
658         record_filepath = args[0]
659         rec_file = self.get_record_file(record_filepath)
660         record = load_record_from_file(rec_file).as_dict()
661         return self.registry.register(auth_cred, record)
662     
663     # update named registry entry
664     def update(self,opts, args):
665         user_cred = self.get_user_cred()
666         rec_file = self.get_record_file(args[0])
667         record = load_record_from_file(rec_file)
668         if record['type'] == "user":
669             if record.get_name() == user_cred.get_gid_object().get_hrn():
670                 cred = user_cred.save_to_string(save_parents=True)
671             else:
672                 cred = self.get_auth_cred().save_to_string(save_parents=True)
673         elif record['type'] in ["slice"]:
674             try:
675                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
676             except ServerException, e:
677                # XXX smbaker -- once we have better error return codes, update this
678                # to do something better than a string compare
679                if "Permission error" in e.args[0]:
680                    cred = self.get_auth_cred().save_to_string(save_parents=True)
681                else:
682                    raise
683         elif record.get_type() in ["authority"]:
684             cred = self.get_auth_cred().save_to_string(save_parents=True)
685         elif record.get_type() == 'node':
686             cred = self.get_auth_cred().save_to_string(save_parents=True)
687         else:
688             raise "unknown record type" + record.get_type()
689         record = record.as_dict()
690         return self.registry.update(cred, record)
691   
692     def get_trusted_certs(self, opts, args):
693         """
694         return the trusted certs at this interface 
695         """ 
696         trusted_certs = self.registry.get_trusted_certs()
697         for trusted_cert in trusted_certs:
698             cert = Certificate(string=trusted_cert)
699             print cert.get_subject()
700         return 
701
702     def aggregates(self, opts, args):
703         """
704         return a list of details about known aggregates
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_aggregates(user_cred, hrn)
711         display_list(result)
712         return 
713
714     def registries(self, opts, args):
715         """
716         return a list of details about known registries
717         """
718         user_cred = self.get_user_cred().save_to_string(save_parents=True)
719         hrn = None
720         if args:
721             hrn = args[0]
722         result = self.registry.get_registries(user_cred, hrn)
723         display_list(result)
724         return
725
726  
727     #
728     # Slice-related commands
729     #
730     
731     # list available nodes -- use 'resources' w/ no argument instead
732
733     # list instantiated slices
734     def slices(self,opts, args):
735         user_cred = self.get_user_cred().save_to_string(save_parents=True)
736         server = self.slicemgr
737         # direct connection to the nodes component manager interface
738         if opts.component:
739             server = self.get_component_server_from_hrn(opts.component)
740         results = server.get_slices(user_cred)
741         display_list(results)
742         return
743     
744     # show rspec for named slice
745     def resources(self,opts, args):
746         user_cred = self.get_user_cred().save_to_string(save_parents=True)
747         server = self.slicemgr
748         if opts.aggregate:
749             agg_hrn = opts.aggregate
750             aggregates = self.registry.get_aggregates(user_cred, agg_hrn)
751             if not aggregates:
752                 raise Exception, "No such aggregate %s" % agg_hrn
753             aggregate = aggregates[0]
754             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
755             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
756         if args:
757             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
758             hrn = args[0]
759         else:
760             cred = user_cred
761             hrn = None
762
763         result = server.get_resources(cred, hrn)
764         format = opts.format
765        
766         display_rspec(result, format)
767         if (opts.file is not None):
768             file = opts.file
769             if not file.startswith(os.sep):
770                 file = os.path.join(self.options.sfi_dir, file)
771             save_rspec_to_file(result, file)
772         return
773     
774     # created named slice with given rspec
775     def create(self,opts, args):
776         slice_hrn = args[0]
777         user_cred = self.get_user_cred()
778         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
779         rspec_file = self.get_rspec_file(args[1])
780         rspec=open(rspec_file).read()
781         server = self.slicemgr
782         if opts.aggregate:
783             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
784             if not aggregates:
785                 raise Exception, "No such aggregate %s" % opts.aggregate
786             aggregate = aggregates[0]
787             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
788             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
789         return server.create_slice(slice_cred, slice_hrn, rspec)
790
791     # get a ticket for the specified slice
792     def get_ticket(self, opts, args):
793         slice_hrn, rspec_path = args[0], args[1]
794         user_cred = self.get_user_cred()
795         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
796         rspec_file = self.get_rspec_file(rspec_path) 
797         rspec=open(rspec_file).read()
798         server = self.slicemgr
799         if opts.aggregate:
800             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
801             if not aggregates:
802                 raise Exception, "No such aggregate %s" % opts.aggregate
803             aggregate = aggregates[0]
804             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
805             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
806         ticket_string = server.get_ticket(slice_cred, slice_hrn, rspec)
807         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
808         print "writing ticket to ", file        
809         ticket = SfaTicket(string=ticket_string)
810         ticket.save_to_file(filename=file, save_parents=True)
811
812     def redeem_ticket(self, opts, args):
813         ticket_file = args[0]
814         
815         # get slice hrn from the ticket
816         # use this to get the right slice credential 
817         ticket = SfaTicket(filename=ticket_file)
818         ticket.decode()
819         slice_hrn=ticket.gidObject.get_hrn()
820         #slice_hrn = ticket.attributes['slivers'][0]['hrn']
821         user_cred = self.get_user_cred()
822         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
823         
824         # get a list node hostnames from the nodespecs in the rspec 
825         rspec = RSpec()
826         rspec.parseString(ticket.rspec)
827         nodespecs = rspec.getDictsByTagName('NodeSpec')
828         hostnames = [nodespec['name'] for nodespec in nodespecs]
829         
830         # create an xmlrpc connection to the component manager at each of these
831         # components and gall redeem_ticket
832         connections = {}
833         for hostname in hostnames:
834             try:
835                 cm_port = "12346" 
836                 url = "https://%(hostname)s:%(cm_port)s" % locals() 
837                 print "Calling redeem_ticket at %(url)s " % locals(),  
838                 cm = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
839                 cm.redeem_ticket(slice_cred, ticket.save_to_string(save_parents=True))
840                 print "Success"
841             except socket.gaierror:
842                 print "Failed:",
843                 print "Componet Manager not accepting requests" 
844             except Exception, e:
845                 print "Failed:", e.message
846              
847         return
848  
849     # delete named slice
850     def delete(self,opts, args):
851         slice_hrn = args[0]
852         server = self.slicemgr
853         # direct connection to the nodes component manager interface
854         if opts.component:
855             server = self.get_component_server_from_hrn(opts.component)
856  
857         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
858         return server.delete_slice(slice_cred, slice_hrn)
859     
860     # start named slice
861     def start(self,opts, args):
862         slice_hrn = args[0]
863         server = self.slicemgr
864         # direct connection to the nodes component manager interface
865         if opts.component:
866             server = self.get_component_server_from_hrn(opts.component)
867  
868         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
869         return server.start_slice(slice_cred, slice_hrn)
870     
871     # stop named slice
872     def stop(self,opts, args):
873         slice_hrn = args[0]
874         server = self.slicemgr
875         # direct connection to the nodes component manager interface
876         if opts.component:
877             server = self.get_component_server_from_hrn(opts.component)
878
879         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
880         return server.stop_slice(slice_cred, slice_hrn)
881     
882     # reset named slice
883     def reset(self,opts, args):
884         slice_hrn = args[0]
885         server = self.slicemgr
886         # direct connection to the nodes component manager interface
887         if opts.component:
888             server = self.get_component_server_from_hrn(opts.component)
889         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
890         return server.reset_slice(slice_cred, slice_hrn)
891     
892     #
893     # Main: parse arguments and dispatch to command
894     #
895     def main(self):
896         parser = self.create_parser()
897         (options, args) = parser.parse_args()
898         self.options = options
899    
900         if options.hashrequest:
901             self.hashrequest=True
902  
903         if len(args) <= 0:
904             print "No command given. Use -h for help."
905             return -1
906     
907         command = args[0]
908         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
909         if self.options.verbose :
910             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
911                                                                    options.sfi_dir, options.user,
912                                                                    options.auth)
913             print "Command %s" %command
914             if command in ("resources"):
915                 print "resources cmd_opts %s" %cmd_opts.format
916             elif command in ("list","show","remove"):
917                 print "cmd_opts.type %s" %cmd_opts.type
918             print "cmd_args %s" %cmd_args
919     
920         self.set_servers()
921     
922         try:
923             self.dispatch(command, cmd_opts, cmd_args)
924         except KeyError:
925             raise 
926             print "Command not found:", command
927             sys.exit(1)
928     
929         return
930     
931 if __name__=="__main__":
932    Sfi().main()