removed another bunch of references to geni
[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("-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.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file)  
307        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file)  
308        return
309     
310     #
311     # Get various credential and spec files
312     #
313     # Establishes limiting conventions
314     #   - conflates MAs and SAs
315     #   - assumes last token in slice name is unique
316     #
317     # Bootstraps credentials
318     #   - bootstrap user credential from self-signed certificate
319     #   - bootstrap authority credential from user credential
320     #   - bootstrap slice credential from user credential
321     #
322     
323     
324     def get_key_file(self):
325        file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
326        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
327        if (os.path.isfile(file)):
328           return file
329        else:
330           print "Key file", file, "does not exist"
331           sys.exit(-1)
332        return
333     
334     def get_cert_file(self,key_file):
335     
336        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
337        file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
338        if (os.path.isfile(file)):
339           return file
340        else:
341           k = Keypair(filename = key_file)
342           cert = Certificate(subject=self.user)
343           cert.set_pubkey(k)
344           cert.set_issuer(k, self.user)
345           cert.sign()
346           if self.options.verbose :
347              print "Writing self-signed certificate to", file
348           cert.save_to_file(file)
349           return file
350    
351     def get_gid(self):
352         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".gid")
353         file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".gid")
354         if (os.path.isfile(file)):
355             gid = GID(filename=file)
356             return gid
357         else:
358             cert_str = self.cert.save_to_string(save_parents=True)
359             gid_str = self.registry.get_gid(cert_str, self.user, "user")
360             gid = GID(string=gid_str)
361             if self.options.verbose:
362                 print "Writing user gid to", file
363             gid.save_to_file(file, save_parents=True)
364             return gid       
365  
366     def get_user_cred(self):
367         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
368         file=os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
369         if (os.path.isfile(file)):
370             user_cred = Credential(filename=file)
371             return user_cred
372         else:
373             # bootstrap user credential
374             cert_string = self.cert.save_to_string(save_parents=True)
375             request_hash = self.key.compute_hash([cert_string, "user", self.user])
376             user_name=self.user.replace(self.authority+".", '')
377             if user_name.count(".") > 0:
378                 user_name = user_name.replace(".", '_')
379                 self.user=self.authority + "." + user_name
380
381             user_cred = self.registry.get_self_credential(cert_string, "user", self.user, request_hash)
382             if user_cred:
383                cred = Credential(string=user_cred)
384                cred.save_to_file(file, save_parents=True)
385                if self.options.verbose:
386                     print "Writing user credential to", file
387                return cred
388             else:
389                print "Failed to get user credential"
390                sys.exit(-1)
391   
392     def get_auth_cred(self):
393         if not self.authority:
394             print "no authority specified. Use -a or set SF_AUTH"
395             sys.exit(-1)
396     
397         file = os.path.join(self.options.sfi_dir, get_leaf("authority") +".cred")
398         if (os.path.isfile(file)):
399             auth_cred = Credential(filename=file)
400             return auth_cred
401         else:
402             # bootstrap authority credential from user credential
403             user_cred = self.get_user_cred().save_to_string(save_parents=True)
404             auth_cred = self.registry.get_credential(user_cred, "authority", self.authority)
405             if auth_cred:
406                 cred = Credential(string=auth_cred)
407                 cred.save_to_file(file, save_parents=True)
408                 if self.options.verbose:
409                     print "Writing authority credential to", file
410                 return cred
411             else:
412                 print "Failed to get authority credential"
413                 sys.exit(-1)
414     
415     def get_slice_cred(self,name):
416         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
417         if (os.path.isfile(file)):
418             slice_cred = Credential(filename=file)
419             return slice_cred
420         else:
421             # bootstrap slice credential from user credential
422             user_cred = self.get_user_cred().save_to_string(save_parents=True)
423             arg_list = [user_cred, "slice", name]
424             slice_cred_str = self.registry.get_credential(user_cred, "slice", name)
425             if slice_cred_str:
426                 slice_cred = Credential(string=slice_cred_str)
427                 slice_cred.save_to_file(file, save_parents=True)
428                 if self.options.verbose:
429                     print "Writing slice credential to", file
430                 return slice_cred
431             else:
432                 print "Failed to get slice credential"
433                 sys.exit(-1)
434     
435     def delegate_cred(self,cred, hrn, type = 'authority'):
436         # the gid and hrn of the object we are delegating
437         user_cred = Credential(string=cred)
438         object_gid = user_cred.get_gid_object()
439         object_hrn = object_gid.get_hrn()
440         #cred.set_delegate(True)
441         #if not cred.get_delegate():
442         #    raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
443            
444     
445         records = self.registry.resolve(cred, hrn)
446         records = filter_records(type, records)
447         
448         if not records:
449             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
450     
451         # the gid of the user who will be delegated too
452         record = SfaRecord(dict=records[0])
453         delegee_gid = record.get_gid_object()
454         delegee_hrn = delegee_gid.get_hrn()
455         
456         # the key and hrn of the user who will be delegating
457         user_key = Keypair(filename = self.get_key_file())
458         user_hrn = user_cred.get_gid_caller().get_hrn()
459     
460         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
461         dcred.set_gid_caller(delegee_gid)
462         dcred.set_gid_object(object_gid)
463         dcred.set_privileges(user_cred.get_privileges())
464         dcred.set_delegate(True)
465         dcred.set_pubkey(object_gid.get_pubkey())
466         dcred.set_issuer(user_key, user_hrn)
467         dcred.set_parent(user_cred)
468         dcred.encode()
469         dcred.sign()
470     
471         return dcred.save_to_string(save_parents=True)
472     
473     def get_rspec_file(self,rspec):
474        if (os.path.isabs(rspec)):
475           file = rspec
476        else:
477           file = os.path.join(self.options.sfi_dir, rspec)
478        if (os.path.isfile(file)):
479           return file
480        else:
481           print "No such rspec file", rspec
482           sys.exit(1)
483     
484     def get_record_file(self,record):
485        if (os.path.isabs(record)):
486           file = record
487        else:
488           file = os.path.join(self.options.sfi_dir, record)
489        if (os.path.isfile(file)):
490           return file
491        else:
492           print "No such registry record file", record
493           sys.exit(1)
494     
495     def load_publickey_string(self,fn):
496        f = file(fn,"r")
497        key_string = f.read()
498     
499        # if the filename is a private key file, then extract the public key
500        if "PRIVATE KEY" in key_string:
501            outfn = tempfile.mktemp()
502            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
503            os.system(cmd)
504            f = file(outfn, "r")
505            key_string = f.read()
506            os.remove(outfn)
507     
508        return key_string
509
510     def get_component_server_from_hrn(self, hrn):
511         # direct connection to the nodes component manager interface
512         user_cred = self.get_user_cred().save_to_string(save_parents=True)
513         records = self.registry.resolve(user_cred, hrn)
514         records = filter_records('node', records)
515         if not records:
516             print "No such component:", opts.component
517         record = records[0]
518         cm_port = "12346"
519         url = "https://%s:%s" % (record['hostname'], cm_port)
520         return xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
521     
522     #
523     # Following functions implement the commands
524     #
525     # Registry-related commands
526     #
527   
528     def dispatch(self,command, cmd_opts, cmd_args):
529         getattr(self,command)(cmd_opts, cmd_args)
530  
531     def gid(self, opts, args):
532         gid = self.get_gid()
533         print "GID: %s" % (gid.save_to_string(save_parents=True))
534         return   
535  
536     # list entires in named authority registry
537     def list(self,opts, args):
538         user_cred = self.get_user_cred().save_to_string(save_parents=True)
539         hrn = args[0]
540         try:
541             list = self.registry.list(user_cred, hrn)
542         except IndexError:
543             raise Exception, "Not enough parameters for the 'list' command"
544           
545         # filter on person, slice, site, node, etc.  
546         # THis really should be in the self.filter_records funct def comment...
547         list = filter_records(opts.type, list)
548         for record in list:
549             print "%s (%s)" % (record['hrn'], record['type'])     
550         if opts.file:
551             file = opts.file
552             if not file.startswith(os.sep):
553                 file = os.path.join(self.options.sfi_dir, file)
554             save_records_to_file(file, list)
555         return
556     
557     # show named registry record
558     def show(self,opts, args):
559         user_cred = self.get_user_cred().save_to_string(save_parents=True)
560         hrn = args[0]
561         records = self.registry.resolve(user_cred, hrn)
562         records = filter_records(opts.type, records)
563         if not records:
564             print "No record of type", opts.type
565         for record in records:
566             if record['type'] in ['user']:
567                 record = UserRecord(dict = record)
568             elif record['type'] in ['slice']:
569                 record = SliceRecord(dict = record)
570             elif record['type'] in ['node']:
571                 record = NodeRecord(dict = record)
572             elif record['type'] in ['authority', 'ma', 'sa']:
573                 record = AuthorityRecord(dict = record)
574             else:
575                 record = SfaRecord(dict = record)
576             if (opts.format=="text"): 
577                 record.dump()  
578             else:
579                 print record.save_to_string() 
580        
581         if opts.file:
582             file = opts.file
583             if not file.startswith(os.sep):
584                 file = os.path.join(self.options.sfi_dir, file)
585             save_records_to_file(file, records)
586         return
587     
588     def delegate(self,opts, args):
589        user_cred = self.get_user_cred()
590        if opts.delegate_user:
591            object_cred = user_cred
592        elif opts.delegate_slice:
593            object_cred = self.get_slice_cred(opts.delegate_slice)
594        else:
595            print "Must specify either --user or --slice <hrn>"
596            return
597     
598        # the gid and hrn of the object we are delegating
599        object_gid = object_cred.get_gid_object()
600        object_hrn = object_gid.get_hrn()
601     
602        if not object_cred.get_delegate():
603            print "Error: Object credential", object_hrn, "does not have delegate bit set"
604            return
605     
606        records = self.registry.resolve(user_cred, args[0])
607        records = filter_records("user", records)
608     
609        if not records:
610            print "Error: Didn't find a user record for", args[0]
611            return
612     
613        # the gid of the user who will be delegated too
614        delegee_gid = records[0].get_gid_object()
615        delegee_hrn = delegee_gid.get_hrn()
616     
617        # the key and hrn of the user who will be delegating
618        user_key = Keypair(filename = self.get_key_file())
619        user_hrn = user_cred.get_gid_caller().get_hrn()
620     
621        dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
622        dcred.set_gid_caller(delegee_gid)
623        dcred.set_gid_object(object_gid)
624        dcred.set_privileges(object_cred.get_privileges())
625        dcred.set_delegate(True)
626        dcred.set_pubkey(object_gid.get_pubkey())
627        dcred.set_issuer(user_key, user_hrn)
628        dcred.set_parent(object_cred)
629        dcred.encode()
630        dcred.sign()
631     
632        if opts.delegate_user:
633            dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_" 
634                                   + get_leaf(object_hrn) + ".cred")
635        elif opts.delegate_slice:
636            dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_" 
637                                   + get_leaf(object_hrn) + ".cred")
638     
639        dcred.save_to_file(dest_fn, save_parents = True)
640     
641        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
642     
643     # removed named registry record
644     #   - have to first retrieve the record to be removed
645     def remove(self,opts, args):
646         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
647         hrn = args[0]
648         type = opts.type 
649         if type in ['all']:
650             type = '*'
651         return self.registry.remove(auth_cred, type, hrn)
652     
653     # add named registry record
654     def add(self,opts, args):
655         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
656         record_filepath = args[0]
657         rec_file = self.get_record_file(record_filepath)
658         record = load_record_from_file(rec_file).as_dict()
659         return self.registry.register(auth_cred, record)
660     
661     # update named registry entry
662     def update(self,opts, args):
663         user_cred = self.get_user_cred()
664         rec_file = self.get_record_file(args[0])
665         record = load_record_from_file(rec_file)
666         if record['type'] == "user":
667             if record.get_name() == user_cred.get_gid_object().get_hrn():
668                 cred = user_cred.save_to_string(save_parents=True)
669             else:
670                 cred = self.get_auth_cred().save_to_string(save_parents=True)
671         elif record['type'] in ["slice"]:
672             try:
673                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
674             except ServerException, e:
675                # XXX smbaker -- once we have better error return codes, update this
676                # to do something better than a string compare
677                if "Permission error" in e.args[0]:
678                    cred = self.get_auth_cred().save_to_string(save_parents=True)
679                else:
680                    raise
681         elif record.get_type() in ["authority"]:
682             cred = self.get_auth_cred().save_to_string(save_parents=True)
683         elif record.get_type() == 'node':
684             cred = self.get_auth_cred().save_to_string(save_parents=True)
685         else:
686             raise "unknown record type" + record.get_type()
687         record = record.as_dict()
688         return self.registry.update(cred, record)
689   
690     def get_trusted_certs(self, opts, args):
691         """
692         return the trusted certs at this interface 
693         """ 
694         trusted_certs = self.registry.get_trusted_certs()
695         for trusted_cert in trusted_certs:
696             cert = Certificate(string=trusted_cert)
697             print cert.get_subject()
698         return 
699
700     def aggregates(self, opts, args):
701         """
702         return a list of details about known aggregates
703         """
704         user_cred = self.get_user_cred().save_to_string(save_parents=True)
705         hrn = None
706         if args: 
707             hrn = args[0]
708         result = self.registry.get_aggregates(user_cred, hrn)
709         display_list(result)
710         return 
711
712     def registries(self, opts, args):
713         """
714         return a list of details about known registries
715         """
716         user_cred = self.get_user_cred().save_to_string(save_parents=True)
717         hrn = None
718         if args:
719             hrn = args[0]
720         result = self.registry.get_registries(user_cred, hrn)
721         display_list(result)
722         return
723
724  
725     #
726     # Slice-related commands
727     #
728     
729     # list available nodes -- use 'resources' w/ no argument instead
730
731     # list instantiated slices
732     def slices(self,opts, args):
733         user_cred = self.get_user_cred().save_to_string(save_parents=True)
734         server = self.slicemgr
735         # direct connection to the nodes component manager interface
736         if opts.component:
737             server = self.get_component_server_from_hrn(opts.component)
738         results = server.get_slices(user_cred)
739         display_list(results)
740         return
741     
742     # show rspec for named slice
743     def resources(self,opts, args):
744         user_cred = self.get_user_cred().save_to_string(save_parents=True)
745         server = self.slicemgr
746         if opts.aggregate:
747             agg_hrn = opts.aggregate
748             aggregates = self.registry.get_aggregates(user_cred, agg_hrn)
749             if not aggregates:
750                 raise Exception, "No such aggregate %s" % agg_hrn
751             aggregate = aggregates[0]
752             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
753             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
754         if args:
755             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
756             hrn = args[0]
757         else:
758             cred = user_cred
759             hrn = None
760
761         result = server.get_resources(cred, hrn)
762         format = opts.format
763        
764         display_rspec(result, format)
765         if (opts.file is not None):
766             file = opts.file
767             if not file.startswith(os.sep):
768                 file = os.path.join(self.options.sfi_dir, file)
769             save_rspec_to_file(result, file)
770         return
771     
772     # created named slice with given rspec
773     def create(self,opts, args):
774         slice_hrn = args[0]
775         user_cred = self.get_user_cred()
776         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
777         rspec_file = self.get_rspec_file(args[1])
778         rspec=open(rspec_file).read()
779         server = self.slicemgr
780         if opts.aggregate:
781             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
782             if not aggregates:
783                 raise Exception, "No such aggregate %s" % opts.aggregate
784             aggregate = aggregates[0]
785             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
786             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.protocol)
787         return server.create_slice(slice_cred, slice_hrn, rspec)
788
789     # get a ticket for the specified slice
790     def get_ticket(self, opts, args):
791         slice_hrn, rspec_path = args[0], args[1]
792         user_cred = self.get_user_cred()
793         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
794         rspec_file = self.get_rspec_file(rspec_path) 
795         rspec=open(rspec_file).read()
796         server = self.slicemgr
797         if opts.aggregate:
798             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
799             if not aggregates:
800                 raise Exception, "No such aggregate %s" % opts.aggregate
801             aggregate = aggregates[0]
802             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
803             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.protocol)
804         ticket_string = server.get_ticket(slice_cred, slice_hrn, rspec)
805         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
806         print "writing ticket to ", file        
807         ticket = SfaTicket(string=ticket_string)
808         ticket.save_to_file(filename=file, save_parents=True)
809
810     def redeem_ticket(self, opts, args):
811         ticket_file = args[0]
812         
813         # get slice hrn from the ticket
814         # use this to get the right slice credential 
815         ticket = SfaTicket(filename=ticket_file)
816         ticket.decode()
817         slice_hrn = ticket.attributes['slivers'][0]['hrn']
818         user_cred = self.get_user_cred()
819         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
820         
821         # get a list node hostnames from the nodespecs in the rspec 
822         rspec = RSpec()
823         rspec.parseString(ticket.rspec)
824         nodespecs = rspec.getDictsByTagName('NodeSpec')
825         hostnames = [nodespec['name'] for nodespec in nodespecs]
826         
827         # create an xmlrpc connection to the component manager at each of these
828         # components and gall redeem_ticket
829         connections = {}
830         for hostname in hostnames:
831             try:
832                 cm_port = "12346" 
833                 url = "https://%(hostname)s:%(cm_port)s" % locals() 
834                 print "Calling get_ticket at %(url)s " % locals(),  
835                 cm = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
836                 cm.redeem_ticket(slice_cred, ticket.save_to_string(save_parents=True))
837                 print "Success"
838             except socket.gaierror:
839                 print "Failed:",
840                 print "Componet Manager not accepting requests" 
841             except Exception, e:
842                 print "Failed:", e.message
843              
844         return
845  
846     # delete named slice
847     def delete(self,opts, args):
848         slice_hrn = args[0]
849         server = self.slicemgr
850         # direct connection to the nodes component manager interface
851         if opts.component:
852             server = self.get_component_server_from_hrn(opts.component)
853  
854         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
855         return server.delete_slice(slice_cred, slice_hrn)
856     
857     # start named slice
858     def start(self,opts, args):
859         slice_hrn = args[0]
860         server = self.slicemgr
861         # direct connection to the nodes component manager interface
862         if opts.component:
863             server = self.get_component_server_from_hrn(opts.component)
864  
865         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
866         return server.start_slice(slice_cred, slice_hrn)
867     
868     # stop named slice
869     def stop(self,opts, args):
870         slice_hrn = args[0]
871         server = self.slicemgr
872         # direct connection to the nodes component manager interface
873         if opts.component:
874             server = self.get_component_server_from_hrn(opts.component)
875
876         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
877         return server.stop_slice(slice_cred, slice_hrn)
878     
879     # reset named slice
880     def reset(self,opts, args):
881         slice_hrn = args[0]
882         server = self.slicemgr
883         # direct connection to the nodes component manager interface
884         if opts.component:
885             server = self.get_component_server_from_hrn(opts.component)
886         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
887         return server.reset_slice(slice_cred, slice_hrn)
888     
889     #
890     # Main: parse arguments and dispatch to command
891     #
892     def main(self):
893         parser = self.create_parser()
894         (options, args) = parser.parse_args()
895         self.options = options
896    
897         if options.hashrequest:
898             self.hashrequest=True
899  
900         if len(args) <= 0:
901             print "No command given. Use -h for help."
902             return -1
903     
904         command = args[0]
905         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
906         if self.options.verbose :
907             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
908                                                                    options.sfi_dir, options.user,
909                                                                    options.auth)
910             print "Command %s" %command
911             if command in ("resources"):
912                 print "resources cmd_opts %s" %cmd_opts.format
913             elif command in ("list","show","remove"):
914                 print "cmd_opts.type %s" %cmd_opts.type
915             print "cmd_args %s" %cmd_args
916     
917         self.set_servers()
918     
919         try:
920             self.dispatch(command, cmd_opts, cmd_args)
921         except KeyError:
922             raise 
923             print "Command not found:", command
924             sys.exit(1)
925     
926         return
927     
928 if __name__=="__main__":
929    Sfi().main()