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