using sfa.util.namespace instead of sfa.util.misc
[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.geniclient import GeniClient
16 from sfa.util.sfaticket import SfaTicket
17 from sfa.util.record import *
18 from sfa.util.namespace import *
19 from sfa.util.rspec import RSpec
20 from sfa.util.xmlrpcprotocol import ServerException
21 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
22 from sfa.util.config import Config
23
24 # utility methods here
25 # display methods
26 def display_rspec(rspec, format = 'rspec'):
27     if format in ['dns']:
28         spec = RSpec()
29         spec.parseString(rspec)
30         hostnames = []
31         nodespecs = spec.getDictsByTagName('NodeSpec')
32         for nodespec in nodespecs:
33             if nodespec.has_key('name') and nodespec['name']:
34                 if isinstance(nodespec['name'], ListType):
35                     hostnames.extend(nodespec['name'])
36                 elif isinstance(nodespec['name'], StringTypes):
37                      hostnames.append(nodespec['name'])
38         result = hostnames
39     elif format in ['ip']:
40         spec = RSpec()
41         spec.parseString(rspec)
42         ips = []
43         ifspecs = spec.getDictsByTagName('IfSpec')
44         for ifspec in ifspecs:
45             if ifspec.has_key('addr') and ifspec['addr']:
46                 ips.append(ifspec['addr'])
47         result = ips
48     else:
49         result = rspec
50
51     print result
52     return
53
54 def display_list(results):
55     for result in results:
56         print result
57
58
59 def display_records(recordList, dump = False):
60     ''' Print all fields in the record'''
61     for record in recordList:
62         display_record(record, dump)
63
64 def display_record(record, dump = False):
65     if dump:
66         record.dump()
67     else:
68         info = record.getdict()
69         print "%s (%s)" % (info['hrn'], info['type'])
70     return
71
72
73 def filter_records(type, records):
74     filtered_records = []
75     for record in records:
76         if (record['type'] == type) or (type == "all"):
77             filtered_records.append(record)
78     return filtered_records
79
80
81 # save methods
82 def save_rspec_to_file(rspec, filename):
83     if not filename.endswith(".rspec"):
84         filename = filename + ".rspec"
85
86     f = open(filename, 'w')
87     f.write(rspec)
88     f.close()
89     return
90
91 def save_records_to_file(filename, recordList):
92     index = 0
93     for record in recordList:
94         if index>0:
95             save_record_to_file(filename + "." + str(index), record)
96         else:
97             save_record_to_file(filename, record)
98         index = index + 1
99
100 def save_record_to_file(filename, record):
101     if record['type'] in ['user']:
102         record = UserRecord(dict = record)
103     elif record['type'] in ['slice']:
104         record = SliceRecord(dict = record)
105     elif record['type'] in ['node']:
106         record = NodeRecord(dict = record)
107     elif record['type'] in ['authority', 'ma', 'sa']:
108         record = AuthorityRecord(dict = record)
109     else:
110         record = GeniRecord(dict = record)
111     str = record.save_to_string()
112     file(filename, "w").write(str)
113     return
114
115
116 # load methods
117 def load_record_from_file(filename):
118     str = file(filename, "r").read()
119     record = GeniRecord(string=str)
120     return record
121
122
123
124 class Sfi:
125     
126     slicemgr = None
127     registry = None
128     user = None
129     authority = None
130     options = None
131     hashrequest = False
132    
133     def create_cmd_parser(self,command, additional_cmdargs = None):
134         cmdargs = {"gid": "",
135                   "list": "name",
136                   "show": "name",
137                   "remove": "name",
138                   "add": "record",
139                   "update": "record",
140                   "aggregates": "[name]",
141                   "registries": "[name]",
142                   "slices": "",
143                   "resources": "[name]",
144                   "create": "name rspec",
145                   "get_trusted_certs": "cred",
146                   "get_ticket": "name rspec",
147                   "redeem_ticket": "ticket",  
148                   "delete": "name",
149                   "reset": "name",
150                   "start": "name",
151                   "stop": "name",
152                   "delegate": "name"
153                  }
154
155         if additional_cmdargs:
156             cmdargs.update(additional_cmdargs)
157
158         if command not in cmdargs:
159             print "Invalid command\n"
160             print "Commands: ",
161             for key in cmdargs.keys():
162                 print key+",",
163             print ""
164             sys.exit(2)
165
166         parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
167                                      % (command, cmdargs[command]))
168
169         if command in ("resources"):
170             parser.add_option("-f", "--format", dest="format",type="choice",
171                              help="display format ([xml]|dns|ip)",default="xml",
172                              choices=("xml","dns","ip"))
173             parser.add_option("-a", "--aggregate", dest="aggregate",
174                              default=None, help="aggregate hrn")
175
176         if command in ("create", "get_ticket"):
177             parser.add_option("-a", "--aggregate", dest="aggregate",default=None,
178                              help="aggregate hrn")
179
180         if command in ("start", "stop", "reset", "delete", "slices"):
181             parser.add_option("-c", "--component", dest="component",default=None,
182                              help="component hrn")
183             
184         if command in ("list", "show", "remove"):
185             parser.add_option("-t", "--type", dest="type",type="choice",
186                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
187                             choices=("all","user","slice","sa","ma","node","aggregate"),
188                             default="all")
189
190         if command in ("resources", "show", "list"):
191            parser.add_option("-o", "--output", dest="file",
192                             help="output XML to file", metavar="FILE", default=None)
193         
194         if command in ("show", "list"):
195            parser.add_option("-f", "--format", dest="format", type="choice",
196                              help="display format ([text]|xml)",default="text",
197                              choices=("text","xml"))
198
199         if command in ("delegate"):
200            parser.add_option("-u", "--user",
201                             action="store_true", dest="delegate_user", default=False,
202                             help="delegate user credential")
203            parser.add_option("-s", "--slice", dest="delegate_slice",
204                             help="delegate slice credential", metavar="HRN", default=None)
205         return parser
206
207         
208     def create_parser(self):
209
210         # Generate command line parser
211         parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
212                              description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
213         parser.add_option("-r", "--registry", dest="registry",
214                          help="root registry", metavar="URL", default=None)
215         parser.add_option("-s", "--slicemgr", dest="sm",
216                          help="slice manager", metavar="URL", default=None)
217         default_sfi_dir=os.path.expanduser("~/.sfi/")
218         parser.add_option("-d", "--dir", dest="sfi_dir",
219                          help="config & working directory - default is " + default_sfi_dir,
220                          metavar="PATH", default = default_sfi_dir)
221         parser.add_option("-u", "--user", dest="user",
222                          help="user name", metavar="HRN", default=None)
223         parser.add_option("-a", "--auth", dest="auth",
224                          help="authority name", metavar="HRN", default=None)
225         parser.add_option("-v", "--verbose",
226                          action="store_true", dest="verbose", default=False,
227                          help="verbose mode")
228         parser.add_option("-p", "--protocol",
229                          dest="protocol", default="xmlrpc",
230                          help="RPC protocol (xmlrpc or soap)")
231         parser.add_option("-k", "--hashrequest",
232                          action="store_true", dest="hashrequest", default=False,
233                          help="Create a hash of the request that will be authenticated on the server")
234         parser.disable_interspersed_args()
235
236         return parser
237         
238  
239     #
240     # Establish Connection to SliceMgr and Registry Servers
241     #
242     def set_servers(self):
243        config_file = self.options.sfi_dir + os.sep + "sfi_config"
244        try:
245           config = Config (config_file)
246        except:
247           print "Failed to read configuration file",config_file
248           print "Make sure to remove the export clauses and to add quotes"
249           if not self.options.verbose:
250              print "Re-run with -v for more details"
251           else:
252              traceback.print_exc()
253           sys.exit(1)
254     
255        errors=0
256        # Set SliceMgr URL
257        if (self.options.sm is not None):
258           sm_url = self.options.sm
259        elif hasattr(config,"SFI_SM"):
260           sm_url = config.SFI_SM
261        else:
262           print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s"%config_file
263           errors +=1 
264     
265        # Set Registry URL
266        if (self.options.registry is not None):
267           reg_url = self.options.registry
268        elif hasattr(config,"SFI_REGISTRY"):
269           reg_url = config.SFI_REGISTRY
270        else:
271           print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s"%config_file
272           errors +=1 
273     
274        # Set user HRN
275        if (self.options.user is not None):
276           self.user = self.options.user
277        elif hasattr(config,"SFI_USER"):
278           self.user = config.SFI_USER
279        else:
280           print "You need to set e.g. SFI_USER='plc.princeton.username' in %s"%config_file
281           errors +=1 
282     
283        # Set authority HRN
284        if (self.options.auth is not None):
285           self.authority = self.options.auth
286        elif hasattr(config,"SFI_AUTH"):
287           self.authority = config.SFI_AUTH
288        else:
289           print "You need to set e.g. SFI_AUTH='plc.princeton' in %s"%config_file
290           errors +=1 
291     
292        if errors:
293           sys.exit(1)
294     
295        if self.options.verbose :
296           print "Contacting Slice Manager at:", sm_url
297           print "Contacting Registry at:", reg_url
298     
299        # Get key and certificate
300        key_file = self.get_key_file()
301        cert_file = self.get_cert_file(key_file)
302        self.key = Keypair(filename=key_file) 
303        self.key_file = key_file
304        self.cert_file = cert_file
305        self.cert = Certificate(filename=cert_file) 
306        # Establish connection to server(s)
307        #self.slicemgr = GeniClient(sm_url, key_file, cert_file, self.options.protocol)
308        #self.registry = GeniClient(reg_url, key_file, cert_file, self.options.protocol)
309        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file)  
310        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file)  
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             request_hash = self.key.compute_hash([cert_string, "user", self.user])
379             user_name=self.user.replace(self.authority+".", '')
380             if user_name.count(".") > 0:
381                 user_name = user_name.replace(".", '_')
382                 self.user=self.authority + "." + user_name
383
384             user_cred = self.registry.get_self_credential(cert_string, "user", self.user, request_hash)
385             if user_cred:
386                cred = Credential(string=user_cred)
387                cred.save_to_file(file, save_parents=True)
388                if self.options.verbose:
389                     print "Writing user credential to", file
390                return cred
391             else:
392                print "Failed to get user credential"
393                sys.exit(-1)
394   
395     def get_auth_cred(self):
396         if not self.authority:
397             print "no authority specified. Use -a or set SF_AUTH"
398             sys.exit(-1)
399     
400         file = os.path.join(self.options.sfi_dir, get_leaf("authority") +".cred")
401         if (os.path.isfile(file)):
402             auth_cred = Credential(filename=file)
403             return auth_cred
404         else:
405             # bootstrap authority credential from user credential
406             user_cred = self.get_user_cred().save_to_string(save_parents=True)
407             auth_cred = self.registry.get_credential(user_cred, "authority", self.authority)
408             if auth_cred:
409                 cred = Credential(string=auth_cred)
410                 cred.save_to_file(file, save_parents=True)
411                 if self.options.verbose:
412                     print "Writing authority credential to", file
413                 return cred
414             else:
415                 print "Failed to get authority credential"
416                 sys.exit(-1)
417     
418     def get_slice_cred(self,name):
419         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
420         if (os.path.isfile(file)):
421             slice_cred = Credential(filename=file)
422             return slice_cred
423         else:
424             # bootstrap slice credential from user credential
425             user_cred = self.get_user_cred().save_to_string(save_parents=True)
426             arg_list = [user_cred, "slice", name]
427             slice_cred_str = self.registry.get_credential(user_cred, "slice", name)
428             if slice_cred_str:
429                 slice_cred = Credential(string=slice_cred_str)
430                 slice_cred.save_to_file(file, save_parents=True)
431                 if self.options.verbose:
432                     print "Writing slice credential to", file
433                 return slice_cred
434             else:
435                 print "Failed to get slice credential"
436                 sys.exit(-1)
437     
438     def delegate_cred(self,cred, hrn, type = 'authority'):
439         # the gid and hrn of the object we are delegating
440         user_cred = Credential(string=cred)
441         object_gid = user_cred.get_gid_object()
442         object_hrn = object_gid.get_hrn()
443         #cred.set_delegate(True)
444         #if not cred.get_delegate():
445         #    raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
446            
447     
448         records = self.registry.resolve(cred, hrn)
449         records = filter_records(type, records)
450         
451         if not records:
452             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
453     
454         # the gid of the user who will be delegated too
455         record = GeniRecord(dict=records[0])
456         delegee_gid = record.get_gid_object()
457         delegee_hrn = delegee_gid.get_hrn()
458         
459         # the key and hrn of the user who will be delegating
460         user_key = Keypair(filename = self.get_key_file())
461         user_hrn = user_cred.get_gid_caller().get_hrn()
462     
463         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
464         dcred.set_gid_caller(delegee_gid)
465         dcred.set_gid_object(object_gid)
466         dcred.set_privileges(user_cred.get_privileges())
467         dcred.set_delegate(True)
468         dcred.set_pubkey(object_gid.get_pubkey())
469         dcred.set_issuer(user_key, user_hrn)
470         dcred.set_parent(user_cred)
471         dcred.encode()
472         dcred.sign()
473     
474         return dcred.save_to_string(save_parents=True)
475     
476     def get_rspec_file(self,rspec):
477        if (os.path.isabs(rspec)):
478           file = rspec
479        else:
480           file = os.path.join(self.options.sfi_dir, rspec)
481        if (os.path.isfile(file)):
482           return file
483        else:
484           print "No such rspec file", rspec
485           sys.exit(1)
486     
487     def get_record_file(self,record):
488        if (os.path.isabs(record)):
489           file = record
490        else:
491           file = os.path.join(self.options.sfi_dir, record)
492        if (os.path.isfile(file)):
493           return file
494        else:
495           print "No such registry record file", record
496           sys.exit(1)
497     
498     def load_publickey_string(self,fn):
499        f = file(fn,"r")
500        key_string = f.read()
501     
502        # if the filename is a private key file, then extract the public key
503        if "PRIVATE KEY" in key_string:
504            outfn = tempfile.mktemp()
505            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
506            os.system(cmd)
507            f = file(outfn, "r")
508            key_string = f.read()
509            os.remove(outfn)
510     
511        return key_string
512
513     def get_component_server_from_hrn(self, hrn):
514         # direct connection to the nodes component manager interface
515         user_cred = self.get_user_cred().save_to_string(save_parents=True)
516         records = self.registry.resolve(user_cred, hrn)
517         records = filter_records('node', records)
518         if not records:
519             print "No such component:", opts.component
520         record = records[0]
521         cm_port = "12346"
522         url = "https://%s:%s" % (record['hostname'], cm_port)
523         return xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
524     
525     #
526     # Following functions implement the commands
527     #
528     # Registry-related commands
529     #
530   
531     def dispatch(self,command, cmd_opts, cmd_args):
532         getattr(self,command)(cmd_opts, cmd_args)
533  
534     def gid(self, opts, args):
535         gid = self.get_gid()
536         print "GID: %s" % (gid.save_to_string(save_parents=True))
537         return   
538  
539     # list entires in named authority registry
540     def list(self,opts, args):
541         user_cred = self.get_user_cred().save_to_string(save_parents=True)
542         hrn = args[0]
543         try:
544             list = self.registry.list(user_cred, hrn)
545         except IndexError:
546             raise Exception, "Not enough parameters for the 'list' command"
547           
548         # filter on person, slice, site, node, etc.  
549         # THis really should be in the self.filter_records funct def comment...
550         list = filter_records(opts.type, list)
551         for record in list:
552             print "%s (%s)" % (record['hrn'], record['type'])     
553         if opts.file:
554             file = opts.file
555             if not file.startswith(os.sep):
556                 file = os.path.join(self.options.sfi_dir, file)
557             save_records_to_file(file, list)
558         return
559     
560     # show named registry record
561     def show(self,opts, args):
562         user_cred = self.get_user_cred().save_to_string(save_parents=True)
563         hrn = args[0]
564         records = self.registry.resolve(user_cred, hrn)
565         records = filter_records(opts.type, records)
566         if not records:
567             print "No record of type", opts.type
568         for record in records:
569             if record['type'] in ['user']:
570                 record = UserRecord(dict = record)
571             elif record['type'] in ['slice']:
572                 record = SliceRecord(dict = record)
573             elif record['type'] in ['node']:
574                 record = NodeRecord(dict = record)
575             elif record['type'] in ['authority', 'ma', 'sa']:
576                 record = AuthorityRecord(dict = record)
577             else:
578                 record = GeniRecord(dict = record)
579             if (opts.format=="text"): 
580                 record.dump()  
581             else:
582                 print record.save_to_string() 
583        
584         if opts.file:
585             file = opts.file
586             if not file.startswith(os.sep):
587                 file = os.path.join(self.options.sfi_dir, file)
588             save_records_to_file(file, records)
589         return
590     
591     def delegate(self,opts, args):
592        user_cred = self.get_user_cred()
593        if opts.delegate_user:
594            object_cred = user_cred
595        elif opts.delegate_slice:
596            object_cred = self.get_slice_cred(opts.delegate_slice)
597        else:
598            print "Must specify either --user or --slice <hrn>"
599            return
600     
601        # the gid and hrn of the object we are delegating
602        object_gid = object_cred.get_gid_object()
603        object_hrn = object_gid.get_hrn()
604     
605        if not object_cred.get_delegate():
606            print "Error: Object credential", object_hrn, "does not have delegate bit set"
607            return
608     
609        records = self.registry.resolve(user_cred, args[0])
610        records = filter_records("user", records)
611     
612        if not records:
613            print "Error: Didn't find a user record for", args[0]
614            return
615     
616        # the gid of the user who will be delegated too
617        delegee_gid = records[0].get_gid_object()
618        delegee_hrn = delegee_gid.get_hrn()
619     
620        # the key and hrn of the user who will be delegating
621        user_key = Keypair(filename = self.get_key_file())
622        user_hrn = user_cred.get_gid_caller().get_hrn()
623     
624        dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
625        dcred.set_gid_caller(delegee_gid)
626        dcred.set_gid_object(object_gid)
627        dcred.set_privileges(object_cred.get_privileges())
628        dcred.set_delegate(True)
629        dcred.set_pubkey(object_gid.get_pubkey())
630        dcred.set_issuer(user_key, user_hrn)
631        dcred.set_parent(object_cred)
632        dcred.encode()
633        dcred.sign()
634     
635        if opts.delegate_user:
636            dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_" 
637                                   + get_leaf(object_hrn) + ".cred")
638        elif opts.delegate_slice:
639            dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_" 
640                                   + get_leaf(object_hrn) + ".cred")
641     
642        dcred.save_to_file(dest_fn, save_parents = True)
643     
644        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
645     
646     # removed named registry record
647     #   - have to first retrieve the record to be removed
648     def remove(self,opts, args):
649         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
650         hrn = args[0]
651         type = opts.type 
652         if type in ['all']:
653             type = '*'
654         return self.registry.remove(auth_cred, type, hrn)
655     
656     # add named registry record
657     def add(self,opts, args):
658         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
659         record_filepath = args[0]
660         rec_file = self.get_record_file(record_filepath)
661         record = load_record_from_file(rec_file).as_dict()
662         return self.registry.register(auth_cred, record)
663     
664     # update named registry entry
665     def update(self,opts, args):
666         user_cred = self.get_user_cred()
667         rec_file = self.get_record_file(args[0])
668         record = load_record_from_file(rec_file)
669         if record['type'] == "user":
670             if record.get_name() == user_cred.get_gid_object().get_hrn():
671                 cred = user_cred.save_to_string(save_parents=True)
672             else:
673                 cred = self.get_auth_cred().save_to_string(save_parents=True)
674         elif record['type'] in ["slice"]:
675             try:
676                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
677             except ServerException, e:
678                # XXX smbaker -- once we have better error return codes, update this
679                # to do something better than a string compare
680                if "Permission error" in e.args[0]:
681                    cred = self.get_auth_cred().save_to_string(save_parents=True)
682                else:
683                    raise
684         elif record.get_type() in ["authority"]:
685             cred = self.get_auth_cred().save_to_string(save_parents=True)
686         elif record.get_type() == 'node':
687             cred = self.get_auth_cred().save_to_string(save_parents=True)
688         else:
689             raise "unknown record type" + record.get_type()
690         record = record.as_dict()
691         return self.registry.update(cred, record)
692   
693     def get_trusted_certs(self, opts, args):
694         """
695         return the trusted certs at this interface 
696         """ 
697         trusted_certs = self.registry.get_trusted_certs()
698         for trusted_cert in trusted_certs:
699             cert = Certificate(string=trusted_cert)
700             print cert.get_subject()
701         return 
702
703     def aggregates(self, opts, args):
704         """
705         return a list of details about known aggregates
706         """
707         user_cred = self.get_user_cred().save_to_string(save_parents=True)
708         hrn = None
709         if args: 
710             hrn = args[0]
711         result = self.registry.get_aggregates(user_cred, hrn)
712         display_list(result)
713         return 
714
715     def registries(self, opts, args):
716         """
717         return a list of details about known registries
718         """
719         user_cred = self.get_user_cred().save_to_string(save_parents=True)
720         hrn = None
721         if args:
722             hrn = args[0]
723         result = self.registry.get_registries(user_cred, hrn)
724         display_list(result)
725         return
726
727  
728     #
729     # Slice-related commands
730     #
731     
732     # list available nodes -- use 'resources' w/ no argument instead
733
734     # list instantiated slices
735     def slices(self,opts, args):
736         user_cred = self.get_user_cred().save_to_string(save_parents=True)
737         server = self.slicemgr
738         # direct connection to the nodes component manager interface
739         if opts.component:
740             server = self.get_component_server_from_hrn(opts.component)
741         results = server.get_slices(user_cred)
742         display_list(results)
743         return
744     
745     # show rspec for named slice
746     def resources(self,opts, args):
747         user_cred = self.get_user_cred().save_to_string(save_parents=True)
748         server = self.slicemgr
749         if opts.aggregate:
750             agg_hrn = opts.aggregate
751             aggregates = self.registry.get_aggregates(user_cred, agg_hrn)
752             if not aggregates:
753                 raise Exception, "No such aggregate %s" % agg_hrn
754             aggregate = aggregates[0]
755             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
756             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
757         if args:
758             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
759             hrn = args[0]
760         else:
761             cred = user_cred
762             hrn = None
763
764         result = server.get_resources(cred, hrn)
765         format = opts.format
766        
767         display_rspec(result, format)
768         if (opts.file is not None):
769             file = opts.file
770             if not file.startswith(os.sep):
771                 file = os.path.join(self.options.sfi_dir, file)
772             save_rspec_to_file(result, file)
773         return
774     
775     # created named slice with given rspec
776     def create(self,opts, args):
777         slice_hrn = args[0]
778         user_cred = self.get_user_cred()
779         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
780         rspec_file = self.get_rspec_file(args[1])
781         rspec=open(rspec_file).read()
782         server = self.slicemgr
783         if opts.aggregate:
784             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
785             if not aggregates:
786                 raise Exception, "No such aggregate %s" % opts.aggregate
787             aggregate = aggregates[0]
788             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
789             server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
790         return server.create_slice(slice_cred, slice_hrn, rspec)
791
792     # get a ticket for the specified slice
793     def get_ticket(self, opts, args):
794         slice_hrn, rspec_path = args[0], args[1]
795         user_cred = self.get_user_cred()
796         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
797         rspec_file = self.get_rspec_file(rspec_path) 
798         rspec=open(rspec_file).read()
799         server = self.slicemgr
800         if opts.aggregate:
801             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
802             if not aggregates:
803                 raise Exception, "No such aggregate %s" % opts.aggregate
804             aggregate = aggregates[0]
805             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
806             server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
807         ticket_string = server.get_ticket(slice_cred, slice_hrn, rspec)
808         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
809         print "writing ticket to ", file        
810         ticket = SfaTicket(string=ticket_string)
811         ticket.save_to_file(filename=file, save_parents=True)
812
813     def redeem_ticket(self, opts, args):
814         ticket_file = args[0]
815         
816         # get slice hrn from the ticket
817         # use this to get the right slice credential 
818         ticket = SfaTicket(filename=ticket_file)
819         ticket.decode()
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 get_ticket at %(url)s " % locals(),  
838                 cm = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
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()