added request_hash argumet some more 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()
564         hrn = None
565         if args: 
566             hrn = args[0]
567         
568         result = self.registry.get_aggregates(user_cred, hrn)
569         self.display_list(result)
570         return 
571
572     def registries(self, opts, args):
573         user_cred = self.get_user_cred()
574         hrn = None
575         if args:
576             hrn = args[0]
577         
578         result = self.registry.get_registries(user_cred, hrn)
579         self.display_list(result)
580         return
581  
582     #
583     # Slice-related commands
584     #
585     
586     # list available nodes -- use 'resources' w/ no argument instead
587
588     # list instantiated slices
589     def slices(self,opts, args):
590        user_cred = self.get_user_cred()
591        results = self.slicemgr.get_slices(user_cred)
592        self.display_list(results)
593        return
594     
595     # show rspec for named slice
596     def resources(self,opts, args):
597        user_cred = self.get_user_cred()
598        server = self.slicemgr
599        if opts.aggregate:
600             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
601             if not aggregates:
602                 raise Exception, "No such aggregate %s" % opts.aggregate
603             aggregate = aggregates[0]
604             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
605             server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
606        if args:
607             slice_cred = self.get_slice_cred(args[0])
608             result = server.get_resources(slice_cred, args[0])
609        else:
610             result = server.get_resources(user_cred)
611        format = opts.format
612        
613        self.display_rspec(result, format)
614        if (opts.file is not None):
615           self.save_rspec_to_file(result, opts.file)
616        return
617     
618     # created named slice with given rspec
619     def create(self,opts, args):
620        slice_hrn = args[0]
621        user_cred = self.get_user_cred()
622        slice_cred = self.get_slice_cred(slice_hrn)
623        rspec_file = self.get_rspec_file(args[1])
624        rspec=open(rspec_file).read()
625        server = self.slicemgr
626        if opts.aggregate:
627            aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
628            if not aggregates:
629                raise Exception, "No such aggregate %s" % opts.aggregate
630            aggregate = aggregates[0]
631            url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
632            server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
633        return server.create_slice(slice_cred, slice_hrn, rspec)
634     
635     # delete named slice
636     def delete(self,opts, args):
637        slice_hrn = args[0]
638        slice_cred = self.get_slice_cred(slice_hrn)
639        
640        return self.slicemgr.delete_slice(slice_cred, slice_hrn)
641     
642     # start named slice
643     def start(self,opts, args):
644        slice_hrn = args[0]
645        slice_cred = self.get_slice_cred(args[0])
646        return self.slicemgr.start_slice(slice_cred, slice_hrn)
647     
648     # stop named slice
649     def stop(self,opts, args):
650        slice_hrn = args[0]
651        slice_cred = self.get_slice_cred(args[0])
652        return self.slicemgr.stop_slice(slice_cred, slice_hrn)
653     
654     # reset named slice
655     def reset(self,opts, args):
656        slice_hrn = args[0]
657        slice_cred = self.get_slice_cred(args[0])
658        return self.slicemgr.reset_slice(slice_cred, slice_hrn)
659     
660     #
661     #
662     # Display, Save, and Filter RSpecs and Records
663     #   - to be replace by EMF-generated routines
664     #
665     #
666     
667     def display_rspec(self,rspec, format = 'rspec'):
668         if format in ['dns']:
669             spec = Rspec()
670             spec.parseString(rspec)
671             hostnames = []
672             nodespecs = spec.getDictsByTagName('NodeSpec')
673             for nodespec in nodespecs:
674                 if nodespec.has_key('name') and nodespec['name']:
675                     if isinstance(nodespec['name'], ListType):
676                         hostnames.extend(nodespec['name'])
677                     elif isinstance(nodespec['name'], StringTypes):
678                         hostnames.append(nodespec['name'])
679             result = hostnames
680         elif format in ['ip']:
681             spec = Rspec()
682             spec.parseString(rspec)
683             ips = []
684             ifspecs = spec.getDictsByTagName('IfSpec')
685             for ifspec in ifspecs:
686                 if ifspec.has_key('addr') and ifspec['addr']:
687                     ips.append(ifspec['addr'])
688             result = ips 
689         else:     
690             result = rspec
691     
692         print result
693         return
694     
695     def display_list(self,results):
696         for result in results:
697             print result
698     
699     def save_rspec_to_file(self,rspec, filename):
700        if not filename.startswith(os.sep):
701            filename = self.options.sfi_dir + filename
702        if not filename.endswith(".rspec"):
703            filename = filename + ".rspec"
704     
705        f = open(filename, 'w')
706        f.write(rspec)
707        f.close()
708        return
709     
710     def display_records(self,recordList, dump = False):
711        ''' Print all fields in the record'''
712        for record in recordList:
713           self.display_record(record, dump)
714     
715     def display_record(self,record, dump = False):
716        if dump:
717            record.dump()
718        else:
719            info = record.getdict()
720            print "%s (%s)" % (info['hrn'], info['type'])
721        return
722     
723     def filter_records(self,type, records):
724        filtered_records = []
725        for record in records:
726            if (record['type'] == type) or (type == "all"):
727                filtered_records.append(record)
728        return filtered_records
729     
730     def save_records_to_file(self,filename, recordList):
731        index = 0
732        for record in recordList:
733            if index>0:
734                self.save_record_to_file(filename + "." + str(index), record)
735            else:
736                self.save_record_to_file(filename, record)
737            index = index + 1
738     
739     def save_record_to_file(self,filename, record):
740        if record['type'] in ['user']:
741            record = UserRecord(dict = record)
742        elif record['type'] in ['slice']:
743            record = SliceRecord(dict = record)
744        elif record['type'] in ['node']:
745            record = NodeRecord(dict = record)
746        elif record['type'] in ['authority', 'ma', 'sa']:
747           record = AuthorityRecord(dict = record)
748        else:
749            record = GeniRecord(dict = record) 
750        if not filename.startswith(os.sep):
751            filename = self.options.sfi_dir + filename
752        str = record.save_to_string()
753        file(filename, "w").write(str)
754        return
755     
756     def load_record_from_file(self,filename):
757        str = file(filename, "r").read()
758        record = GeniRecord(string=str)
759        return record
760     
761     #
762     # Main: parse arguments and dispatch to command
763     #
764     def main(self):
765        parser = self.create_parser()
766        (options, args) = parser.parse_args()
767        self.options = options
768     
769        if len(args) <= 0:
770             print "No command given. Use -h for help."
771             return -1
772     
773        command = args[0]
774        (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
775        if self.options.verbose :
776           print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry,
777                                                                    options.sm,
778                                                                    options.sfi_dir,
779                                                                    options.user,
780                                                                    options.auth)
781           print "Command %s" %command
782           if command in ("resources"):
783              print "resources cmd_opts %s" %cmd_opts.format
784           elif command in ("list","show","remove"):
785              print "cmd_opts.type %s" %cmd_opts.type
786           print "cmd_args %s" %cmd_args
787     
788        self.set_servers()
789     
790        try:
791           self.dispatch(command, cmd_opts, cmd_args)
792        except KeyError:
793           raise 
794           print "Command not found:", command
795           sys.exit(1)
796     
797        return
798     
799 if __name__=="__main__":
800    Sfi().main()