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