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