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