geniclient isnt used anymore
[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 = GeniRecord(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 = GeniRecord(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("-p", "--protocol",
228                          dest="protocol", default="xmlrpc",
229                          help="RPC protocol (xmlrpc or soap)")
230         parser.add_option("-k", "--hashrequest",
231                          action="store_true", dest="hashrequest", default=False,
232                          help="Create a hash of the request that will be authenticated on the server")
233         parser.disable_interspersed_args()
234
235         return parser
236         
237  
238     #
239     # Establish Connection to SliceMgr and Registry Servers
240     #
241     def set_servers(self):
242        config_file = self.options.sfi_dir + os.sep + "sfi_config"
243        try:
244           config = Config (config_file)
245        except:
246           print "Failed to read configuration file",config_file
247           print "Make sure to remove the export clauses and to add quotes"
248           if not self.options.verbose:
249              print "Re-run with -v for more details"
250           else:
251              traceback.print_exc()
252           sys.exit(1)
253     
254        errors=0
255        # Set SliceMgr URL
256        if (self.options.sm is not None):
257           sm_url = self.options.sm
258        elif hasattr(config,"SFI_SM"):
259           sm_url = config.SFI_SM
260        else:
261           print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s"%config_file
262           errors +=1 
263     
264        # Set Registry URL
265        if (self.options.registry is not None):
266           reg_url = self.options.registry
267        elif hasattr(config,"SFI_REGISTRY"):
268           reg_url = config.SFI_REGISTRY
269        else:
270           print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s"%config_file
271           errors +=1 
272     
273        # Set user HRN
274        if (self.options.user is not None):
275           self.user = self.options.user
276        elif hasattr(config,"SFI_USER"):
277           self.user = config.SFI_USER
278        else:
279           print "You need to set e.g. SFI_USER='plc.princeton.username' in %s"%config_file
280           errors +=1 
281     
282        # Set authority HRN
283        if (self.options.auth is not None):
284           self.authority = self.options.auth
285        elif hasattr(config,"SFI_AUTH"):
286           self.authority = config.SFI_AUTH
287        else:
288           print "You need to set e.g. SFI_AUTH='plc.princeton' in %s"%config_file
289           errors +=1 
290     
291        if errors:
292           sys.exit(1)
293     
294        if self.options.verbose :
295           print "Contacting Slice Manager at:", sm_url
296           print "Contacting Registry at:", reg_url
297     
298        # Get key and certificate
299        key_file = self.get_key_file()
300        cert_file = self.get_cert_file(key_file)
301        self.key = Keypair(filename=key_file) 
302        self.key_file = key_file
303        self.cert_file = cert_file
304        self.cert = Certificate(filename=cert_file) 
305        # Establish connection to server(s)
306        #self.slicemgr = GeniClient(sm_url, key_file, cert_file, self.options.protocol)
307        #self.registry = GeniClient(reg_url, key_file, cert_file, self.options.protocol)
308        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file)  
309        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file)  
310        return
311     
312     #
313     # Get various credential and spec files
314     #
315     # Establishes limiting conventions
316     #   - conflates MAs and SAs
317     #   - assumes last token in slice name is unique
318     #
319     # Bootstraps credentials
320     #   - bootstrap user credential from self-signed certificate
321     #   - bootstrap authority credential from user credential
322     #   - bootstrap slice credential from user credential
323     #
324     
325     
326     def get_key_file(self):
327        file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
328        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
329        if (os.path.isfile(file)):
330           return file
331        else:
332           print "Key file", file, "does not exist"
333           sys.exit(-1)
334        return
335     
336     def get_cert_file(self,key_file):
337     
338        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
339        file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
340        if (os.path.isfile(file)):
341           return file
342        else:
343           k = Keypair(filename = key_file)
344           cert = Certificate(subject=self.user)
345           cert.set_pubkey(k)
346           cert.set_issuer(k, self.user)
347           cert.sign()
348           if self.options.verbose :
349              print "Writing self-signed certificate to", file
350           cert.save_to_file(file)
351           return file
352    
353     def get_gid(self):
354         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".gid")
355         file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".gid")
356         if (os.path.isfile(file)):
357             gid = GID(filename=file)
358             return gid
359         else:
360             cert_str = self.cert.save_to_string(save_parents=True)
361             gid_str = self.registry.get_gid(cert_str, self.user, "user")
362             gid = GID(string=gid_str)
363             if self.options.verbose:
364                 print "Writing user gid to", file
365             gid.save_to_file(file, save_parents=True)
366             return gid       
367  
368     def get_user_cred(self):
369         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
370         file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
371         if (os.path.isfile(file)):
372             user_cred = Credential(filename=file)
373             return user_cred
374         else:
375             # bootstrap user credential
376             cert_string = self.cert.save_to_string(save_parents=True)
377             request_hash = self.key.compute_hash([cert_string, "user", self.user])
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, request_hash)
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 = GeniRecord(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)
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 = GeniRecord(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, 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 = records[0].get_gid_object()
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     
623        dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
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)
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 = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
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 = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
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.attributes['slivers'][0]['hrn']
820         user_cred = self.get_user_cred()
821         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
822         
823         # get a list node hostnames from the nodespecs in the rspec 
824         rspec = RSpec()
825         rspec.parseString(ticket.rspec)
826         nodespecs = rspec.getDictsByTagName('NodeSpec')
827         hostnames = [nodespec['name'] for nodespec in nodespecs]
828         
829         # create an xmlrpc connection to the component manager at each of these
830         # components and gall redeem_ticket
831         connections = {}
832         for hostname in hostnames:
833             try:
834                 cm_port = "12346" 
835                 url = "https://%(hostname)s:%(cm_port)s" % locals() 
836                 print "Calling get_ticket at %(url)s " % locals(),  
837                 cm = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
838                 cm.redeem_ticket(slice_cred, ticket.save_to_string(save_parents=True))
839                 print "Success"
840             except socket.gaierror:
841                 print "Failed:",
842                 print "Componet Manager not accepting requests" 
843             except Exception, e:
844                 print "Failed:", e.message
845              
846         return
847  
848     # delete named slice
849     def delete(self,opts, args):
850         slice_hrn = args[0]
851         server = self.slicemgr
852         # direct connection to the nodes component manager interface
853         if opts.component:
854             server = self.get_component_server_from_hrn(opts.component)
855  
856         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
857         return server.delete_slice(slice_cred, slice_hrn)
858     
859     # start named slice
860     def start(self,opts, args):
861         slice_hrn = args[0]
862         server = self.slicemgr
863         # direct connection to the nodes component manager interface
864         if opts.component:
865             server = self.get_component_server_from_hrn(opts.component)
866  
867         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
868         return server.start_slice(slice_cred, slice_hrn)
869     
870     # stop named slice
871     def stop(self,opts, args):
872         slice_hrn = args[0]
873         server = self.slicemgr
874         # direct connection to the nodes component manager interface
875         if opts.component:
876             server = self.get_component_server_from_hrn(opts.component)
877
878         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
879         return server.stop_slice(slice_cred, slice_hrn)
880     
881     # reset named slice
882     def reset(self,opts, args):
883         slice_hrn = args[0]
884         server = self.slicemgr
885         # direct connection to the nodes component manager interface
886         if opts.component:
887             server = self.get_component_server_from_hrn(opts.component)
888         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
889         return server.reset_slice(slice_cred, slice_hrn)
890     
891     #
892     # Main: parse arguments and dispatch to command
893     #
894     def main(self):
895         parser = self.create_parser()
896         (options, args) = parser.parse_args()
897         self.options = options
898    
899         if options.hashrequest:
900             self.hashrequest=True
901  
902         if len(args) <= 0:
903             print "No command given. Use -h for help."
904             return -1
905     
906         command = args[0]
907         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
908         if self.options.verbose :
909             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
910                                                                    options.sfi_dir, options.user,
911                                                                    options.auth)
912             print "Command %s" %command
913             if command in ("resources"):
914                 print "resources cmd_opts %s" %cmd_opts.format
915             elif command in ("list","show","remove"):
916                 print "cmd_opts.type %s" %cmd_opts.type
917             print "cmd_args %s" %cmd_args
918     
919         self.set_servers()
920     
921         try:
922             self.dispatch(command, cmd_opts, cmd_args)
923         except KeyError:
924             raise 
925             print "Command not found:", command
926             sys.exit(1)
927     
928         return
929     
930 if __name__=="__main__":
931    Sfi().main()