request_hash was taken out from the code. It still appears in few part of the code...
[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             user_name=self.user.replace(self.authority+".", '')
376             if user_name.count(".") > 0:
377                 user_name = user_name.replace(".", '_')
378                 self.user=self.authority + "." + user_name
379
380             user_cred = self.registry.get_self_credential(cert_string, "user", self.user)
381             if user_cred:
382                cred = Credential(string=user_cred)
383                cred.save_to_file(file, save_parents=True)
384                if self.options.verbose:
385                     print "Writing user credential to", file
386                return cred
387             else:
388                print "Failed to get user credential"
389                sys.exit(-1)
390   
391     def get_auth_cred(self):
392         if not self.authority:
393             print "no authority specified. Use -a or set SF_AUTH"
394             sys.exit(-1)
395     
396         file = os.path.join(self.options.sfi_dir, get_leaf("authority") +".cred")
397         if (os.path.isfile(file)):
398             auth_cred = Credential(filename=file)
399             return auth_cred
400         else:
401             # bootstrap authority credential from user credential
402             user_cred = self.get_user_cred().save_to_string(save_parents=True)
403             auth_cred = self.registry.get_credential(user_cred, "authority", self.authority)
404             if auth_cred:
405                 cred = Credential(string=auth_cred)
406                 cred.save_to_file(file, save_parents=True)
407                 if self.options.verbose:
408                     print "Writing authority credential to", file
409                 return cred
410             else:
411                 print "Failed to get authority credential"
412                 sys.exit(-1)
413     
414     def get_slice_cred(self,name):
415         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
416         if (os.path.isfile(file)):
417             slice_cred = Credential(filename=file)
418             return slice_cred
419         else:
420             # bootstrap slice credential from user credential
421             user_cred = self.get_user_cred().save_to_string(save_parents=True)
422             arg_list = [user_cred, "slice", name]
423             slice_cred_str = self.registry.get_credential(user_cred, "slice", name)
424             if slice_cred_str:
425                 slice_cred = Credential(string=slice_cred_str)
426                 slice_cred.save_to_file(file, save_parents=True)
427                 if self.options.verbose:
428                     print "Writing slice credential to", file
429                 return slice_cred
430             else:
431                 print "Failed to get slice credential"
432                 sys.exit(-1)
433     
434     def delegate_cred(self,cred, hrn, type = 'authority'):
435         # the gid and hrn of the object we are delegating
436         user_cred = Credential(string=cred)
437         object_gid = user_cred.get_gid_object()
438         object_hrn = object_gid.get_hrn()
439         #cred.set_delegate(True)
440         #if not cred.get_delegate():
441         #    raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
442            
443     
444         records = self.registry.resolve(cred, hrn)
445         records = filter_records(type, records)
446         
447         if not records:
448             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
449     
450         # the gid of the user who will be delegated too
451         record = SfaRecord(dict=records[0])
452         delegee_gid = record.get_gid_object()
453         delegee_hrn = delegee_gid.get_hrn()
454         
455         # the key and hrn of the user who will be delegating
456         user_key = Keypair(filename = self.get_key_file())
457         user_hrn = user_cred.get_gid_caller().get_hrn()
458     
459         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
460         dcred.set_gid_caller(delegee_gid)
461         dcred.set_gid_object(object_gid)
462         dcred.set_privileges(user_cred.get_privileges())
463         dcred.set_delegate(True)
464         dcred.set_pubkey(object_gid.get_pubkey())
465         dcred.set_issuer(user_key, user_hrn)
466         dcred.set_parent(user_cred)
467         dcred.encode()
468         dcred.sign()
469     
470         return dcred.save_to_string(save_parents=True)
471     
472     def get_rspec_file(self,rspec):
473        if (os.path.isabs(rspec)):
474           file = rspec
475        else:
476           file = os.path.join(self.options.sfi_dir, rspec)
477        if (os.path.isfile(file)):
478           return file
479        else:
480           print "No such rspec file", rspec
481           sys.exit(1)
482     
483     def get_record_file(self,record):
484        if (os.path.isabs(record)):
485           file = record
486        else:
487           file = os.path.join(self.options.sfi_dir, record)
488        if (os.path.isfile(file)):
489           return file
490        else:
491           print "No such registry record file", record
492           sys.exit(1)
493     
494     def load_publickey_string(self,fn):
495        f = file(fn,"r")
496        key_string = f.read()
497     
498        # if the filename is a private key file, then extract the public key
499        if "PRIVATE KEY" in key_string:
500            outfn = tempfile.mktemp()
501            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
502            os.system(cmd)
503            f = file(outfn, "r")
504            key_string = f.read()
505            os.remove(outfn)
506     
507        return key_string
508
509     def get_component_server_from_hrn(self, hrn):
510         # direct connection to the nodes component manager interface
511         user_cred = self.get_user_cred().save_to_string(save_parents=True)
512         records = self.registry.resolve(user_cred, hrn)
513         records = filter_records('node', records)
514         if not records:
515             print "No such component:", opts.component
516         record = records[0]
517         cm_port = "12346"
518         url = "https://%s:%s" % (record['hostname'], cm_port)
519         return xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
520     
521     #
522     # Following functions implement the commands
523     #
524     # Registry-related commands
525     #
526   
527     def dispatch(self,command, cmd_opts, cmd_args):
528         getattr(self,command)(cmd_opts, cmd_args)
529  
530     def gid(self, opts, args):
531         gid = self.get_gid()
532         print "GID: %s" % (gid.save_to_string(save_parents=True))
533         return   
534  
535     # list entires in named authority registry
536     def list(self,opts, args):
537         user_cred = self.get_user_cred().save_to_string(save_parents=True)
538         hrn = args[0]
539         try:
540             list = self.registry.list(user_cred, hrn)
541         except IndexError:
542             raise Exception, "Not enough parameters for the 'list' command"
543           
544         # filter on person, slice, site, node, etc.  
545         # THis really should be in the self.filter_records funct def comment...
546         list = filter_records(opts.type, list)
547         for record in list:
548             print "%s (%s)" % (record['hrn'], record['type'])     
549         if opts.file:
550             file = opts.file
551             if not file.startswith(os.sep):
552                 file = os.path.join(self.options.sfi_dir, file)
553             save_records_to_file(file, list)
554         return
555     
556     # show named registry record
557     def show(self,opts, args):
558         user_cred = self.get_user_cred().save_to_string(save_parents=True)
559         hrn = args[0]
560         records = self.registry.resolve(user_cred, hrn)
561         records = filter_records(opts.type, records)
562         if not records:
563             print "No record of type", opts.type
564         for record in records:
565             if record['type'] in ['user']:
566                 record = UserRecord(dict = record)
567             elif record['type'] in ['slice']:
568                 record = SliceRecord(dict = record)
569             elif record['type'] in ['node']:
570                 record = NodeRecord(dict = record)
571             elif record['type'] in ['authority', 'ma', 'sa']:
572                 record = AuthorityRecord(dict = record)
573             else:
574                 record = SfaRecord(dict = record)
575             if (opts.format=="text"): 
576                 record.dump()  
577             else:
578                 print record.save_to_string() 
579        
580         if opts.file:
581             file = opts.file
582             if not file.startswith(os.sep):
583                 file = os.path.join(self.options.sfi_dir, file)
584             save_records_to_file(file, records)
585         return
586     
587     def delegate(self,opts, args):
588        user_cred = self.get_user_cred()
589        if opts.delegate_user:
590            object_cred = user_cred
591        elif opts.delegate_slice:
592            object_cred = self.get_slice_cred(opts.delegate_slice)
593        else:
594            print "Must specify either --user or --slice <hrn>"
595            return
596     
597        # the gid and hrn of the object we are delegating
598        object_gid = object_cred.get_gid_object()
599        object_hrn = object_gid.get_hrn()
600     
601        if not object_cred.get_delegate():
602            print "Error: Object credential", object_hrn, "does not have delegate bit set"
603            return
604     
605        records = self.registry.resolve(user_cred, args[0])
606        records = filter_records("user", records)
607     
608        if not records:
609            print "Error: Didn't find a user record for", args[0]
610            return
611     
612        # the gid of the user who will be delegated too
613        delegee_gid = records[0].get_gid_object()
614        delegee_hrn = delegee_gid.get_hrn()
615     
616        # the key and hrn of the user who will be delegating
617        user_key = Keypair(filename = self.get_key_file())
618        user_hrn = user_cred.get_gid_caller().get_hrn()
619     
620        dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
621        dcred.set_gid_caller(delegee_gid)
622        dcred.set_gid_object(object_gid)
623        dcred.set_privileges(object_cred.get_privileges())
624        dcred.set_delegate(True)
625        dcred.set_pubkey(object_gid.get_pubkey())
626        dcred.set_issuer(user_key, user_hrn)
627        dcred.set_parent(object_cred)
628        dcred.encode()
629        dcred.sign()
630     
631        if opts.delegate_user:
632            dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_" 
633                                   + get_leaf(object_hrn) + ".cred")
634        elif opts.delegate_slice:
635            dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_" 
636                                   + get_leaf(object_hrn) + ".cred")
637     
638        dcred.save_to_file(dest_fn, save_parents = True)
639     
640        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
641     
642     # removed named registry record
643     #   - have to first retrieve the record to be removed
644     def remove(self,opts, args):
645         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
646         hrn = args[0]
647         type = opts.type 
648         if type in ['all']:
649             type = '*'
650         return self.registry.remove(auth_cred, type, hrn)
651     
652     # add named registry record
653     def add(self,opts, args):
654         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
655         record_filepath = args[0]
656         rec_file = self.get_record_file(record_filepath)
657         record = load_record_from_file(rec_file).as_dict()
658         return self.registry.register(auth_cred, record)
659     
660     # update named registry entry
661     def update(self,opts, args):
662         user_cred = self.get_user_cred()
663         rec_file = self.get_record_file(args[0])
664         record = load_record_from_file(rec_file)
665         if record['type'] == "user":
666             if record.get_name() == user_cred.get_gid_object().get_hrn():
667                 cred = user_cred.save_to_string(save_parents=True)
668             else:
669                 cred = self.get_auth_cred().save_to_string(save_parents=True)
670         elif record['type'] in ["slice"]:
671             try:
672                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
673             except ServerException, e:
674                # XXX smbaker -- once we have better error return codes, update this
675                # to do something better than a string compare
676                if "Permission error" in e.args[0]:
677                    cred = self.get_auth_cred().save_to_string(save_parents=True)
678                else:
679                    raise
680         elif record.get_type() in ["authority"]:
681             cred = self.get_auth_cred().save_to_string(save_parents=True)
682         elif record.get_type() == 'node':
683             cred = self.get_auth_cred().save_to_string(save_parents=True)
684         else:
685             raise "unknown record type" + record.get_type()
686         record = record.as_dict()
687         return self.registry.update(cred, record)
688   
689     def get_trusted_certs(self, opts, args):
690         """
691         return the trusted certs at this interface 
692         """ 
693         trusted_certs = self.registry.get_trusted_certs()
694         for trusted_cert in trusted_certs:
695             cert = Certificate(string=trusted_cert)
696             print cert.get_subject()
697         return 
698
699     def aggregates(self, opts, args):
700         """
701         return a list of details about known aggregates
702         """
703         user_cred = self.get_user_cred().save_to_string(save_parents=True)
704         hrn = None
705         if args: 
706             hrn = args[0]
707         result = self.registry.get_aggregates(user_cred, hrn)
708         display_list(result)
709         return 
710
711     def registries(self, opts, args):
712         """
713         return a list of details about known registries
714         """
715         user_cred = self.get_user_cred().save_to_string(save_parents=True)
716         hrn = None
717         if args:
718             hrn = args[0]
719         result = self.registry.get_registries(user_cred, hrn)
720         display_list(result)
721         return
722
723  
724     #
725     # Slice-related commands
726     #
727     
728     # list available nodes -- use 'resources' w/ no argument instead
729
730     # list instantiated slices
731     def slices(self,opts, args):
732         user_cred = self.get_user_cred().save_to_string(save_parents=True)
733         server = self.slicemgr
734         # direct connection to the nodes component manager interface
735         if opts.component:
736             server = self.get_component_server_from_hrn(opts.component)
737         results = server.get_slices(user_cred)
738         display_list(results)
739         return
740     
741     # show rspec for named slice
742     def resources(self,opts, args):
743         user_cred = self.get_user_cred().save_to_string(save_parents=True)
744         server = self.slicemgr
745         if opts.aggregate:
746             agg_hrn = opts.aggregate
747             aggregates = self.registry.get_aggregates(user_cred, agg_hrn)
748             if not aggregates:
749                 raise Exception, "No such aggregate %s" % agg_hrn
750             aggregate = aggregates[0]
751             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
752             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
753         if args:
754             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
755             hrn = args[0]
756         else:
757             cred = user_cred
758             hrn = None
759
760         result = server.get_resources(cred, hrn)
761         format = opts.format
762        
763         display_rspec(result, format)
764         if (opts.file is not None):
765             file = opts.file
766             if not file.startswith(os.sep):
767                 file = os.path.join(self.options.sfi_dir, file)
768             save_rspec_to_file(result, file)
769         return
770     
771     # created named slice with given rspec
772     def create(self,opts, args):
773         slice_hrn = args[0]
774         user_cred = self.get_user_cred()
775         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
776         rspec_file = self.get_rspec_file(args[1])
777         rspec=open(rspec_file).read()
778         server = self.slicemgr
779         if opts.aggregate:
780             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
781             if not aggregates:
782                 raise Exception, "No such aggregate %s" % opts.aggregate
783             aggregate = aggregates[0]
784             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
785             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.protocol)
786         return server.create_slice(slice_cred, slice_hrn, rspec)
787
788     # get a ticket for the specified slice
789     def get_ticket(self, opts, args):
790         slice_hrn, rspec_path = args[0], args[1]
791         user_cred = self.get_user_cred()
792         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
793         rspec_file = self.get_rspec_file(rspec_path) 
794         rspec=open(rspec_file).read()
795         server = self.slicemgr
796         if opts.aggregate:
797             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
798             if not aggregates:
799                 raise Exception, "No such aggregate %s" % opts.aggregate
800             aggregate = aggregates[0]
801             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
802             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.protocol)
803         ticket_string = server.get_ticket(slice_cred, slice_hrn, rspec)
804         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
805         print "writing ticket to ", file        
806         ticket = SfaTicket(string=ticket_string)
807         ticket.save_to_file(filename=file, save_parents=True)
808
809     def redeem_ticket(self, opts, args):
810         ticket_file = args[0]
811         
812         # get slice hrn from the ticket
813         # use this to get the right slice credential 
814         ticket = SfaTicket(filename=ticket_file)
815         ticket.decode()
816         slice_hrn=ticket.gidObject.get_hrn()
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 redeem_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()