Changed Rspec --> RSpec throughout.
[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     #
30     # Establish Connection to SliceMgr and Registry Servers
31     #
32     def set_servers(self):
33        config_file = self.options.sfi_dir + os.sep + "sfi_config"
34        try:
35           config = Config (config_file)
36        except:
37           print "Failed to read configuration file",config_file
38           print "Make sure to remove the export clauses and to add quotes"
39           if not self.options.verbose:
40              print "Re-run with -v for more details"
41           else:
42              traceback.print_exc()
43           sys.exit(1)
44     
45        errors=0
46        # Set SliceMgr URL
47        if (self.options.sm is not None):
48           sm_url = self.options.sm
49        elif hasattr(config,"SFI_SM"):
50           sm_url = config.SFI_SM
51        else:
52           print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s"%config_file
53           errors +=1 
54     
55        # Set Registry URL
56        if (self.options.registry is not None):
57           reg_url = self.options.registry
58        elif hasattr(config,"SFI_REGISTRY"):
59           reg_url = config.SFI_REGISTRY
60        else:
61           print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s"%config_file
62           errors +=1 
63     
64        # Set user HRN
65        if (self.options.user is not None):
66           self.user = self.options.user
67        elif hasattr(config,"SFI_USER"):
68           self.user = config.SFI_USER
69        else:
70           print "You need to set e.g. SFI_USER='plc.princeton.username' in %s"%config_file
71           errors +=1 
72     
73        # Set authority HRN
74        if (self.options.auth is not None):
75           self.authority = self.options.auth
76        elif hasattr(config,"SFI_AUTH"):
77           self.authority = config.SFI_AUTH
78        else:
79           print "You need to set e.g. SFI_AUTH='plc.princeton' in %s"%config_file
80           errors +=1 
81     
82        if errors:
83           sys.exit(1)
84     
85        if self.options.verbose :
86           print "Contacting Slice Manager at:", sm_url
87           print "Contacting Registry at:", reg_url
88     
89        # Get key and certificate
90        key_file = self.get_key_file()
91        cert_file = self.get_cert_file(key_file)
92        self.key = Keypair(filename=key_file) 
93        self.key_file = key_file
94        self.cert_file = cert_file
95        self.cert = Certificate(filename=cert_file) 
96        # Establish connection to server(s)
97        #self.slicemgr = GeniClient(sm_url, key_file, cert_file, self.options.protocol)
98        #self.registry = GeniClient(reg_url, key_file, cert_file, self.options.protocol)
99        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file)  
100        self.slicemgr = xmlrpcprotocol.get_server(sm_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             cert_string = self.cert.save_to_string(save_parents=True)
168             request_hash = self.key.compute_hash([cert_string, "user", self.user])
169             user_cred = self.registry.get_self_credential(cert_string, "user", self.user, request_hash)
170             if user_cred:
171                cred = Credential(string=user_cred)
172                cred.save_to_file(file, save_parents=True)
173                if self.options.verbose:
174                     print "Writing user credential to", file
175                return cred
176             else:
177                print "Failed to get user credential"
178                sys.exit(-1)
179     
180     def get_auth_cred(self):
181     
182        if not self.authority:
183           print "no authority specified. Use -a or set SF_AUTH"
184           sys.exit(-1)
185     
186        file = os.path.join(self.options.sfi_dir, self.get_leaf("authority") +".cred")
187        if (os.path.isfile(file)):
188           auth_cred = Credential(filename=file)
189           return auth_cred
190        else:
191           # bootstrap authority credential from user credential
192           user_cred = self.get_user_cred().save_to_string(save_parents=True)
193           request_hash = self.key.compute_hash([user_cred, "authority", self.authority])
194           auth_cred = self.registry.get_credential(user_cred, "authority", self.authority, request_hash)
195           if auth_cred:
196              cred = Credential(string=auth_cred)
197              cred.save_to_file(file, save_parents=True)
198              if self.options.verbose:
199                 print "Writing authority credential to", file
200              return cred
201           else:
202              print "Failed to get authority credential"
203              sys.exit(-1)
204     
205     def get_slice_cred(self,name):
206        file = os.path.join(self.options.sfi_dir, "slice_" + self.get_leaf(name) + ".cred")
207        if (os.path.isfile(file)):
208           slice_cred = Credential(filename=file)
209           return slice_cred
210        else:
211           # bootstrap slice credential from user credential
212           user_cred = self.get_user_cred().save_to_string(save_parents=True)
213           arg_list = [user_cred, "slice", name]
214           request_hash = self.key.compute_hash(arg_list)  
215           slice_cred_str = self.registry.get_credential(user_cred, "slice", name, request_hash)
216           if slice_cred:
217              slice_cred = Credential(string=slice_cred_str)
218              slice_cred.save_to_file(file, save_parents=True)
219              if self.options.verbose:
220                 print "Writing slice credential to", file
221              return slice_cred
222           else:
223              print "Failed to get slice credential"
224              sys.exit(-1)
225     
226     def delegate_cred(self,cred, hrn, type = 'authority'):
227         # the gid and hrn of the object we are delegating
228         object_gid = cred.get_gid_object()
229         object_hrn = object_gid.get_hrn()
230         cred.set_delegate(True)
231         if not cred.get_delegate():
232             raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
233            
234     
235         records = self.registry.resolve(cred, hrn)
236         records = self.filter_records(type, records)
237         
238         if not records:
239             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
240     
241         # the gid of the user who will be delegated too
242         delegee_gid = records[0].get_gid_object()
243         delegee_hrn = delegee_gid.get_hrn()
244         
245         # the key and hrn of the user who will be delegating
246         user_key = Keypair(filename = self.get_key_file())
247         user_hrn = cred.get_gid_caller().get_hrn()
248     
249         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
250         dcred.set_gid_caller(delegee_gid)
251         dcred.set_gid_object(object_gid)
252         dcred.set_privileges(cred.get_privileges())
253         dcred.set_delegate(True)
254         dcred.set_pubkey(object_gid.get_pubkey())
255         dcred.set_issuer(user_key, user_hrn)
256         dcred.set_parent(cred)
257         dcred.encode()
258         dcred.sign()
259     
260         return dcred
261     
262     def get_rspec_file(self,rspec):
263        if (os.path.isabs(rspec)):
264           file = rspec
265        else:
266           file = os.path.join(self.options.sfi_dir, rspec)
267        if (os.path.isfile(file)):
268           return file
269        else:
270           print "No such rspec file", rspec
271           sys.exit(1)
272     
273     def get_record_file(self,record):
274        if (os.path.isabs(record)):
275           file = record
276        else:
277           file = os.path.join(self.options.sfi_dir, record)
278        if (os.path.isfile(file)):
279           return file
280        else:
281           print "No such registry record file", record
282           sys.exit(1)
283     
284     def load_publickey_string(self,fn):
285        f = file(fn,"r")
286        key_string = f.read()
287     
288        # if the filename is a private key file, then extract the public key
289        if "PRIVATE KEY" in key_string:
290            outfn = tempfile.mktemp()
291            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
292            os.system(cmd)
293            f = file(outfn, "r")
294            key_string = f.read()
295            os.remove(outfn)
296     
297        return key_string
298     #
299     # Generate sub-command parser
300     #
301     def create_cmd_parser(self,command, additional_cmdargs = None):
302        cmdargs = {"gid": "",
303                   "list": "name",
304                   "show": "name",
305                   "remove": "name",
306                   "add": "record",
307                   "update": "record",
308                   "aggregates": "[name]",
309                   "registries": "[name]",   
310                   "slices": "",
311                   "resources": "[name]",
312                   "create": "name rspec",
313                   "delete": "name",
314                   "reset": "name",
315                   "start": "name",
316                   "stop": "name",
317                   "delegate": "name"
318                  }
319     
320        if additional_cmdargs:
321           cmdargs.update(additional_cmdargs)
322     
323        if command not in cmdargs:
324           print "Invalid command\n"
325           print "Commands: ",
326           for key in cmdargs.keys():
327               print key+",",
328           print ""
329           sys.exit(2)
330     
331        parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
332           % (command, cmdargs[command]))
333
334        if command in ("resources"):
335            parser.add_option("-f", "--format", dest="format",type="choice",
336                              help="display format ([xml]|dns|ip)",default="xml",
337                              choices=("xml","dns","ip"))
338            parser.add_option("-a", "--aggregate", dest="aggregate",
339                              default=None, help="aggregate hrn")  
340     
341        if command in ("create"):
342            parser.add_option("-a", "--aggregate", dest="aggregate",default=None,
343                              help="aggregate hrn") 
344  
345        if command in ("list", "show", "remove"):
346           parser.add_option("-t", "--type", dest="type",type="choice",
347                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
348                             choices=("all","user","slice","sa","ma","node","aggregate"),
349                             default="all")
350
351        if command in ("resources", "show", "list"):
352           parser.add_option("-o", "--output", dest="file",
353                             help="output XML to file", metavar="FILE", default=None)
354
355        if command in ("show", "list"):
356            parser.add_option("-f", "--format", dest="format", type="choice", 
357                              help="display format ([text]|xml)",default="text", 
358                              choices=("text","xml")) 
359
360        if command in ("delegate"):
361           parser.add_option("-u", "--user",
362                             action="store_true", dest="delegate_user", default=False,
363                             help="delegate user credential")
364           parser.add_option("-s", "--slice", dest="delegate_slice",
365                             help="delegate slice credential", metavar="HRN", default=None)
366        return parser
367     
368     def create_parser(self):
369
370        # Generate command line parser
371        parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
372                              description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
373        parser.add_option("-r", "--registry", dest="registry",
374                          help="root registry", metavar="URL", default=None)
375        parser.add_option("-s", "--slicemgr", dest="sm",
376                          help="slice manager", metavar="URL", default=None)
377        default_sfi_dir=os.path.expanduser("~/.sfi/")
378        parser.add_option("-d", "--dir", dest="sfi_dir",
379                          help="config & working directory - default is " + default_sfi_dir,
380                          metavar="PATH", default = default_sfi_dir)
381        parser.add_option("-u", "--user", dest="user",
382                          help="user name", metavar="HRN", default=None)
383        parser.add_option("-a", "--auth", dest="auth",
384                          help="authority name", metavar="HRN", default=None)
385        parser.add_option("-v", "--verbose",
386                          action="store_true", dest="verbose", default=False,
387                          help="verbose mode")
388        parser.add_option("-p", "--protocol",
389                          dest="protocol", default="xmlrpc",
390                          help="RPC protocol (xmlrpc or soap)")
391        parser.disable_interspersed_args()
392     
393        return parser
394     
395     def dispatch(self,command, cmd_opts, cmd_args):
396        getattr(self,command)(cmd_opts, cmd_args)
397     
398     #
399     # Following functions implement the commands
400     #
401     # Registry-related commands
402     #
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()