moved utility methods out of Sfi class. added get_ticket method
[sfa.git] / sfa / client / sfi.py
1 #! /usr/bin/env python
2
3 # sfi -- slice-based facility interface
4
5 import sys
6 import os, os.path
7 import tempfile
8 import traceback
9 from types import StringTypes, ListType
10 from optparse import OptionParser
11
12 from sfa.trust.certificate import Keypair, Certificate
13 from sfa.trust.credential import Credential
14 from sfa.util.geniclient import GeniClient
15 from sfa.util.sfaticket import SfaTicket
16 from sfa.util.record import *
17 from sfa.util.misc 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_ticket": "name rspec",
145                   "delete": "name",
146                   "reset": "name",
147                   "start": "name",
148                   "stop": "name",
149                   "delegate": "name"
150                  }
151
152         if additional_cmdargs:
153             cmdargs.update(additional_cmdargs)
154
155         if command not in cmdargs:
156             print "Invalid command\n"
157             print "Commands: ",
158             for key in cmdargs.keys():
159                 print key+",",
160             print ""
161             sys.exit(2)
162
163         parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
164                                      % (command, cmdargs[command]))
165
166         if command in ("resources"):
167             parser.add_option("-f", "--format", dest="format",type="choice",
168                              help="display format ([xml]|dns|ip)",default="xml",
169                              choices=("xml","dns","ip"))
170             parser.add_option("-a", "--aggregate", dest="aggregate",
171                              default=None, help="aggregate hrn")
172
173         if command in ("create", "get_ticket"):
174             parser.add_option("-a", "--aggregate", dest="aggregate",default=None,
175                              help="aggregate hrn")
176
177         if command in ("list", "show", "remove"):
178             parser.add_option("-t", "--type", dest="type",type="choice",
179                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
180                             choices=("all","user","slice","sa","ma","node","aggregate"),
181                             default="all")
182
183         if command in ("resources", "show", "list"):
184            parser.add_option("-o", "--output", dest="file",
185                             help="output XML to file", metavar="FILE", default=None)
186         
187         if command in ("show", "list"):
188            parser.add_option("-f", "--format", dest="format", type="choice",
189                              help="display format ([text]|xml)",default="text",
190                              choices=("text","xml"))
191
192         if command in ("delegate"):
193            parser.add_option("-u", "--user",
194                             action="store_true", dest="delegate_user", default=False,
195                             help="delegate user credential")
196            parser.add_option("-s", "--slice", dest="delegate_slice",
197                             help="delegate slice credential", metavar="HRN", default=None)
198         return parser
199
200         
201     def create_parser(self):
202
203         # Generate command line parser
204         parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
205                              description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
206         parser.add_option("-r", "--registry", dest="registry",
207                          help="root registry", metavar="URL", default=None)
208         parser.add_option("-s", "--slicemgr", dest="sm",
209                          help="slice manager", metavar="URL", default=None)
210         default_sfi_dir=os.path.expanduser("~/.sfi/")
211         parser.add_option("-d", "--dir", dest="sfi_dir",
212                          help="config & working directory - default is " + default_sfi_dir,
213                          metavar="PATH", default = default_sfi_dir)
214         parser.add_option("-u", "--user", dest="user",
215                          help="user name", metavar="HRN", default=None)
216         parser.add_option("-a", "--auth", dest="auth",
217                          help="authority name", metavar="HRN", default=None)
218         parser.add_option("-v", "--verbose",
219                          action="store_true", dest="verbose", default=False,
220                          help="verbose mode")
221         parser.add_option("-p", "--protocol",
222                          dest="protocol", default="xmlrpc",
223                          help="RPC protocol (xmlrpc or soap)")
224         parser.add_option("-k", "--hashrequest",
225                          action="store_true", dest="hashrequest", default=False,
226                          help="Create a hash of the request that will be authenticated on the server")
227         parser.disable_interspersed_args()
228
229         return parser
230         
231  
232     #
233     # Establish Connection to SliceMgr and Registry Servers
234     #
235     def set_servers(self):
236        config_file = self.options.sfi_dir + os.sep + "sfi_config"
237        try:
238           config = Config (config_file)
239        except:
240           print "Failed to read configuration file",config_file
241           print "Make sure to remove the export clauses and to add quotes"
242           if not self.options.verbose:
243              print "Re-run with -v for more details"
244           else:
245              traceback.print_exc()
246           sys.exit(1)
247     
248        errors=0
249        # Set SliceMgr URL
250        if (self.options.sm is not None):
251           sm_url = self.options.sm
252        elif hasattr(config,"SFI_SM"):
253           sm_url = config.SFI_SM
254        else:
255           print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s"%config_file
256           errors +=1 
257     
258        # Set Registry URL
259        if (self.options.registry is not None):
260           reg_url = self.options.registry
261        elif hasattr(config,"SFI_REGISTRY"):
262           reg_url = config.SFI_REGISTRY
263        else:
264           print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s"%config_file
265           errors +=1 
266     
267        # Set user HRN
268        if (self.options.user is not None):
269           self.user = self.options.user
270        elif hasattr(config,"SFI_USER"):
271           self.user = config.SFI_USER
272        else:
273           print "You need to set e.g. SFI_USER='plc.princeton.username' in %s"%config_file
274           errors +=1 
275     
276        # Set authority HRN
277        if (self.options.auth is not None):
278           self.authority = self.options.auth
279        elif hasattr(config,"SFI_AUTH"):
280           self.authority = config.SFI_AUTH
281        else:
282           print "You need to set e.g. SFI_AUTH='plc.princeton' in %s"%config_file
283           errors +=1 
284     
285        if errors:
286           sys.exit(1)
287     
288        if self.options.verbose :
289           print "Contacting Slice Manager at:", sm_url
290           print "Contacting Registry at:", reg_url
291     
292        # Get key and certificate
293        key_file = self.get_key_file()
294        cert_file = self.get_cert_file(key_file)
295        self.key = Keypair(filename=key_file) 
296        self.key_file = key_file
297        self.cert_file = cert_file
298        self.cert = Certificate(filename=cert_file) 
299        # Establish connection to server(s)
300        #self.slicemgr = GeniClient(sm_url, key_file, cert_file, self.options.protocol)
301        #self.registry = GeniClient(reg_url, key_file, cert_file, self.options.protocol)
302        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file)  
303        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file)  
304        return
305     
306     #
307     # Get various credential and spec files
308     #
309     # Establishes limiting conventions
310     #   - conflates MAs and SAs
311     #   - assumes last token in slice name is unique
312     #
313     # Bootstraps credentials
314     #   - bootstrap user credential from self-signed certificate
315     #   - bootstrap authority credential from user credential
316     #   - bootstrap slice credential from user credential
317     #
318     
319     
320     def get_key_file(self):
321        file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
322        if (os.path.isfile(file)):
323           return file
324        else:
325           print "Key file", file, "does not exist"
326           sys.exit(-1)
327        return
328     
329     def get_cert_file(self,key_file):
330     
331        file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
332        if (os.path.isfile(file)):
333           return file
334        else:
335           k = Keypair(filename = key_file)
336           cert = Certificate(subject=self.user)
337           cert.set_pubkey(k)
338           cert.set_issuer(k, self.user)
339           cert.sign()
340           if self.options.verbose :
341              print "Writing self-signed certificate to", file
342           cert.save_to_file(file)
343           return file
344    
345     def get_gid(self):
346         file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".gid")
347         if (os.path.isfile(file)):
348             gid = GID(filename=file)
349             return gid
350         else:
351             cert_str = self.cert.save_to_string(save_parents=True)
352             request_hash=None
353             if self.hashrequest:
354                 request_hash = self.key.compute_hash([cert_str, self.user, "user"])
355             gid_str = self.registry.get_gid(cert_str, self.user, "user", request_hash)
356             gid = GID(string=gid_str)
357             if self.options.verbose:
358                 print "Writing user gid to", file
359             gid.save_to_file(file, save_parents=True)
360             return gid       
361  
362     def get_user_cred(self):
363         file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
364         if (os.path.isfile(file)):
365             user_cred = Credential(filename=file)
366             return user_cred
367         else:
368             # bootstrap user credential
369             cert_string = self.cert.save_to_string(save_parents=True)
370             request_hash=None
371             if self.hashrequest:
372                 request_hash = self.key.compute_hash([cert_string, "user", self.user])
373             user_cred = self.registry.get_self_credential(cert_string, "user", self.user, request_hash)
374             if user_cred:
375                cred = Credential(string=user_cred)
376                cred.save_to_file(file, save_parents=True)
377                if self.options.verbose:
378                     print "Writing user credential to", file
379                return cred
380             else:
381                print "Failed to get user credential"
382                sys.exit(-1)
383   
384     def get_auth_cred(self):
385         if not self.authority:
386             print "no authority specified. Use -a or set SF_AUTH"
387             sys.exit(-1)
388     
389         file = os.path.join(self.options.sfi_dir, get_leaf("authority") +".cred")
390         if (os.path.isfile(file)):
391             auth_cred = Credential(filename=file)
392             return auth_cred
393         else:
394             # bootstrap authority credential from user credential
395             user_cred = self.get_user_cred().save_to_string(save_parents=True)
396             request_hash = None
397             if self.hashrequest:
398                 request_hash = self.key.compute_hash([user_cred, "authority", self.authority])
399             auth_cred = self.registry.get_credential(user_cred, "authority", self.authority, request_hash)
400             if auth_cred:
401                 cred = Credential(string=auth_cred)
402                 cred.save_to_file(file, save_parents=True)
403                 if self.options.verbose:
404                     print "Writing authority credential to", file
405                 return cred
406             else:
407                 print "Failed to get authority credential"
408                 sys.exit(-1)
409     
410     def get_slice_cred(self,name):
411         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
412         if (os.path.isfile(file)):
413             slice_cred = Credential(filename=file)
414             return slice_cred
415         else:
416             # bootstrap slice credential from user credential
417             user_cred = self.get_user_cred().save_to_string(save_parents=True)
418             arg_list = [user_cred, "slice", name]
419             request_hash=None
420             if self.hashrequest:
421                 request_hash = self.key.compute_hash(arg_list)  
422             slice_cred_str = self.registry.get_credential(user_cred, "slice", name, request_hash)
423             if slice_cred_str:
424                 slice_cred = Credential(string=slice_cred_str)
425                 slice_cred.save_to_file(file, save_parents=True)
426                 if self.options.verbose:
427                     print "Writing slice credential to", file
428                 return slice_cred
429             else:
430                 print "Failed to get slice credential"
431                 sys.exit(-1)
432     
433     def delegate_cred(self,cred, hrn, type = 'authority'):
434         # the gid and hrn of the object we are delegating
435         object_gid = cred.get_gid_object()
436         object_hrn = object_gid.get_hrn()
437         cred.set_delegate(True)
438         if not cred.get_delegate():
439             raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
440            
441     
442         records = self.registry.resolve(cred, hrn)
443         records = filter_records(type, records)
444         
445         if not records:
446             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
447     
448         # the gid of the user who will be delegated too
449         delegee_gid = records[0].get_gid_object()
450         delegee_hrn = delegee_gid.get_hrn()
451         
452         # the key and hrn of the user who will be delegating
453         user_key = Keypair(filename = self.get_key_file())
454         user_hrn = cred.get_gid_caller().get_hrn()
455     
456         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
457         dcred.set_gid_caller(delegee_gid)
458         dcred.set_gid_object(object_gid)
459         dcred.set_privileges(cred.get_privileges())
460         dcred.set_delegate(True)
461         dcred.set_pubkey(object_gid.get_pubkey())
462         dcred.set_issuer(user_key, user_hrn)
463         dcred.set_parent(cred)
464         dcred.encode()
465         dcred.sign()
466     
467         return dcred
468     
469     def get_rspec_file(self,rspec):
470        if (os.path.isabs(rspec)):
471           file = rspec
472        else:
473           file = os.path.join(self.options.sfi_dir, rspec)
474        if (os.path.isfile(file)):
475           return file
476        else:
477           print "No such rspec file", rspec
478           sys.exit(1)
479     
480     def get_record_file(self,record):
481        if (os.path.isabs(record)):
482           file = record
483        else:
484           file = os.path.join(self.options.sfi_dir, record)
485        if (os.path.isfile(file)):
486           return file
487        else:
488           print "No such registry record file", record
489           sys.exit(1)
490     
491     def load_publickey_string(self,fn):
492        f = file(fn,"r")
493        key_string = f.read()
494     
495        # if the filename is a private key file, then extract the public key
496        if "PRIVATE KEY" in key_string:
497            outfn = tempfile.mktemp()
498            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
499            os.system(cmd)
500            f = file(outfn, "r")
501            key_string = f.read()
502            os.remove(outfn)
503     
504        return key_string
505     
506     #
507     # Following functions implement the commands
508     #
509     # Registry-related commands
510     #
511   
512     def dispatch(self,command, cmd_opts, cmd_args):
513         getattr(self,command)(cmd_opts, cmd_args)
514  
515     def gid(self, opts, args):
516         gid = self.get_gid()
517         print "GID: %s" % (gid.save_to_string(save_parents=True))
518         return   
519  
520     # list entires in named authority registry
521     def list(self,opts, args):
522         user_cred = self.get_user_cred().save_to_string(save_parents=True)
523         hrn = args[0]
524         request_hash=None
525         if self.hashrequest:
526             request_hash = self.key.compute_hash([user_cred, hrn])    
527         try:
528             list = self.registry.list(user_cred, hrn, request_hash)
529         except IndexError:
530             raise Exception, "Not enough parameters for the 'list' command"
531           
532         # filter on person, slice, site, node, etc.  
533         # THis really should be in the self.filter_records funct def comment...
534         list = filter_records(opts.type, list)
535         for record in list:
536             print "%s (%s)" % (record['hrn'], record['type'])     
537         if opts.file:
538             file = opts.file
539             if not file.startswith(os.sep):
540                 file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".gid")
541             save_records_to_file(file, list)
542         return
543     
544     # show named registry record
545     def show(self,opts, args):
546         user_cred = self.get_user_cred().save_to_string(save_parents=True)
547         hrn = args[0]
548         request_hash=None
549         if self.hashrequest:
550             request_hash = self.key.compute_hash([user_cred, hrn])    
551         records = self.registry.resolve(user_cred, hrn, request_hash)
552         records = filter_records(opts.type, records)
553         if not records:
554             print "No record of type", opts.type
555         for record in records:
556             if record['type'] in ['user']:
557                 record = UserRecord(dict = record)
558             elif record['type'] in ['slice']:
559                 record = SliceRecord(dict = record)
560             elif record['type'] in ['node']:
561                 record = NodeRecord(dict = record)
562             elif record['type'] in ['authority', 'ma', 'sa']:
563                 record = AuthorityRecord(dict = record)
564             else:
565                 record = GeniRecord(dict = record)
566             if (opts.format=="text"): 
567                 record.dump()  
568             else: 
569                 print record.save_to_string() 
570        
571         if opts.file:
572             file = opts.file
573             if not file.startswith(os.sep):
574                 file = os.path.join(self.options.sfi_dir, file)
575             save_records_to_file(file, records)
576         return
577     
578     def delegate(self,opts, args):
579        user_cred = self.get_user_cred()
580        if opts.delegate_user:
581            object_cred = user_cred
582        elif opts.delegate_slice:
583            object_cred = self.get_slice_cred(opts.delegate_slice)
584        else:
585            print "Must specify either --user or --slice <hrn>"
586            return
587     
588        # the gid and hrn of the object we are delegating
589        object_gid = object_cred.get_gid_object()
590        object_hrn = object_gid.get_hrn()
591     
592        if not object_cred.get_delegate():
593            print "Error: Object credential", object_hrn, "does not have delegate bit set"
594            return
595     
596        records = self.registry.resolve(user_cred, args[0])
597        records = filter_records("user", records)
598     
599        if not records:
600            print "Error: Didn't find a user record for", args[0]
601            return
602     
603        # the gid of the user who will be delegated too
604        delegee_gid = records[0].get_gid_object()
605        delegee_hrn = delegee_gid.get_hrn()
606     
607        # the key and hrn of the user who will be delegating
608        user_key = Keypair(filename = self.get_key_file())
609        user_hrn = user_cred.get_gid_caller().get_hrn()
610     
611        dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
612        dcred.set_gid_caller(delegee_gid)
613        dcred.set_gid_object(object_gid)
614        dcred.set_privileges(object_cred.get_privileges())
615        dcred.set_delegate(True)
616        dcred.set_pubkey(object_gid.get_pubkey())
617        dcred.set_issuer(user_key, user_hrn)
618        dcred.set_parent(object_cred)
619        dcred.encode()
620        dcred.sign()
621     
622        if opts.delegate_user:
623            dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_" 
624                                   + get_leaf(object_hrn) + ".cred")
625        elif opts.delegate_slice:
626            dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_" 
627                                   + get_leaf(object_hrn) + ".cred")
628     
629        dcred.save_to_file(dest_fn, save_parents = True)
630     
631        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
632     
633     # removed named registry record
634     #   - have to first retrieve the record to be removed
635     def remove(self,opts, args):
636         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
637         hrn = args[0]
638         type = opts.type 
639         if type in ['all']:
640             type = '*'
641         request_hash=None
642         if self.hashrequest: 
643             arg_list = [auth_cred, type, hrn]
644             request_hash = self.key.compute_hash(arg_list)                   
645         return self.registry.remove(auth_cred, type, hrn, request_hash)
646     
647     # add named registry record
648     def add(self,opts, args):
649         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
650         record_filepath = args[0]
651         rec_file = self.get_record_file(record_filepath)
652         record = load_record_from_file(rec_file).as_dict()
653         request_hash=None
654         if self.hashrequest:
655             arg_list = [auth_cred]
656             request_hash = self.key.compute_hash(arg_list)
657         return self.registry.register(auth_cred, record, request_hash)
658     
659     # update named registry entry
660     def update(self,opts, args):
661         user_cred = self.get_user_cred()
662         rec_file = self.get_record_file(args[0])
663         record = load_record_from_file(rec_file)
664         if record['type'] == "user":
665             if record.get_name() == user_cred.get_gid_object().get_hrn():
666                 cred = user_cred.save_to_string(save_parents=True)
667             else:
668                 cred = self.get_auth_cred().save_to_string(save_parents=True)
669         elif record['type'] in ["slice"]:
670             try:
671                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
672             except ServerException, e:
673                # XXX smbaker -- once we have better error return codes, update this
674                # to do something better than a string compare
675                if "Permission error" in e.args[0]:
676                    cred = self.get_auth_cred().save_to_string(save_parents=True)
677                else:
678                    raise
679         elif record.get_type() in ["authority"]:
680             cred = self.get_auth_cred().save_to_string(save_parents=True)
681         elif record.get_type() == 'node':
682             cred = self.get_auth_cred().save_to_string(save_parents=True)
683         else:
684             raise "unknown record type" + record.get_type()
685         record = record.as_dict()
686         request_hash=None
687         if self.hashrequest:
688             arg_list = [cred]  
689             request_hash = self.key.compute_hash(arg_list)
690         return self.registry.update(cred, record, request_hash)
691    
692     
693     def aggregates(self, opts, args):
694         user_cred = self.get_user_cred().save_to_string(save_parents=True)
695         hrn = None
696         if args: 
697             hrn = args[0]
698         request_hash=None
699         if self.hashrequest:
700             arg_list = [user_cred, hrn]  
701             request_hash = self.key.compute_hash(arg_list)
702         result = self.registry.get_aggregates(user_cred, hrn, request_hash)
703         display_list(result)
704         return 
705
706     def registries(self, opts, args):
707         user_cred = self.get_user_cred().save_to_string(save_parents=True)
708         hrn = None
709         if args:
710             hrn = args[0]
711         request_hash=None
712         if self.hashrequest:
713             arg_list = [user_cred, hrn]  
714             request_hash = self.key.compute_hash(arg_list)
715         result = self.registry.get_registries(user_cred, hrn, request_hash)
716         display_list(result)
717         return
718  
719     #
720     # Slice-related commands
721     #
722     
723     # list available nodes -- use 'resources' w/ no argument instead
724
725     # list instantiated slices
726     def slices(self,opts, args):
727         user_cred = self.get_user_cred().save_to_string(save_parents=True)
728         request_hash=None
729         if self.hashrequest:
730             arg_list = [user_cred]
731             request_hash = self.key.compute_hash(arg_list)
732         results = self.slicemgr.get_slices(user_cred, request_hash)
733         display_list(results)
734         return
735     
736     # show rspec for named slice
737     def resources(self,opts, args):
738         user_cred = self.get_user_cred().save_to_string(save_parents=True)
739         server = self.slicemgr
740         if opts.aggregate:
741             agg_hrn = opts.aggregate
742             arg_list = [user_cred, arg_hrn]
743             request_hash = self.key.compute_hash(arg_list)
744             aggregates = self.registry.get_aggregates(user_cred, agg_hrn, request_hash)
745             if not aggregates:
746                 raise Exception, "No such aggregate %s" % agg_hrn
747             aggregate = aggregates[0]
748             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
749             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
750         if args:
751             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
752             hrn = args[0]
753         else:
754             cred = user_cred
755             hrn = None
756
757         request_hash=None
758         if self.hashrequest:
759             arg_list = [cred, hrn]
760             request_hash = self.key.compute_hash(arg_list)  
761         result = server.get_resources(cred, hrn, request_hash)
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 = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
787         request_hash=None
788         if self.hashrequest:
789             arg_list = [slice_cred, slice_hrn, rspec]
790             request_hash = self.key.compute_hash(arg_list) 
791         return server.create_slice(slice_cred, slice_hrn, rspec, request_hash)
792
793     # get a ticket for the specified slice
794     def get_ticket(self, opts, args):
795         slice_hrn, rspec_path = args[0], args[1]
796         user_cred = self.get_user_cred()
797         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
798         rspec_file = self.get_rspec_file(rspec_path) 
799         rspec=open(rspec_file).read()
800         server = self.slicemgr
801         if opts.aggregate:
802             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
803             if not aggregates:
804                 raise Exception, "No such aggregate %s" % opts.aggregate
805             aggregate = aggregates[0]
806             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
807             server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
808         request_hash=None
809         if self.hashrequest:
810             arg_list = [slice_cred, slice_hrn, rspec]
811             request_hash = self.key.compute_hash(arg_list)
812         ticket_string = server.get_ticket(slice_cred, slice_hrn, rspec, request_hash)
813         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
814         print "writing ticket to ", file        
815         ticket = SfaTicket(string=ticket_string)
816         ticket.save_to_file(filename=file, save_parents=True)
817         print ticket_string  
818  
819     # delete named slice
820     def delete(self,opts, args):
821         slice_hrn = args[0]
822         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
823         request_hash=None
824         if self.hashrequest:
825             arg_list = [slice_cred, slice_hrn]
826             request_hash = self.key.compute_hash(arg_list) 
827         return self.slicemgr.delete_slice(slice_cred, slice_hrn, request_hash)
828     
829     # start named slice
830     def start(self,opts, args):
831         slice_hrn = args[0]
832         slice_cred = self.get_slice_cred(args[0])
833         request_hash=None
834         if self.hashrequest:
835             arg_list = [slice_cred, slice_hrn]
836             request_hash = self.key.compute_hash(arg_list)
837         return self.slicemgr.start_slice(slice_cred, slice_hrn, request_hash)
838     
839     # stop named slice
840     def stop(self,opts, args):
841         slice_hrn = args[0]
842         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
843         request_hash=None
844         if self.hashrequest:
845             arg_list = [slice_cred, slice_hrn]
846             request_hash = self.key.compute_hash(arg_list)
847         return self.slicemgr.stop_slice(slice_cred, slice_hrn, request_hash)
848     
849     # reset named slice
850     def reset(self,opts, args):
851         slice_hrn = args[0]
852         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
853         request_hash=None
854         if self.hashrequest:
855             arg_list = [slice_cred, slice_hrn]
856             request_hash = self.key.compute_hash(arg_list)
857         return self.slicemgr.reset_slice(slice_cred, slice_hrn, request_hash)
858     
859     #
860     # Main: parse arguments and dispatch to command
861     #
862     def main(self):
863         parser = self.create_parser()
864         (options, args) = parser.parse_args()
865         self.options = options
866    
867         if options.hashrequest:
868             self.hashrequest=True
869  
870         if len(args) <= 0:
871             print "No command given. Use -h for help."
872             return -1
873     
874         command = args[0]
875         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
876         if self.options.verbose :
877             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
878                                                                    options.sfi_dir, options.user,
879                                                                    options.auth)
880             print "Command %s" %command
881             if command in ("resources"):
882                 print "resources cmd_opts %s" %cmd_opts.format
883             elif command in ("list","show","remove"):
884                 print "cmd_opts.type %s" %cmd_opts.type
885             print "cmd_args %s" %cmd_args
886     
887         self.set_servers()
888     
889         try:
890             self.dispatch(command, cmd_opts, cmd_args)
891         except KeyError:
892             raise 
893             print "Command not found:", command
894             sys.exit(1)
895     
896         return
897     
898 if __name__=="__main__":
899    Sfi().main()