Changed Rspec --> RSpec throughout.
[sfa.git] / sfa / client / sfi.py
index f55c66e..b3dbf35 100755 (executable)
@@ -11,11 +11,11 @@ from optparse import OptionParser
 
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.credential import Credential
-
 from sfa.util.geniclient import GeniClient
 from sfa.util.record import *
-from sfa.util.rspec import Rspec
+from sfa.util.rspec import RSpec
 from sfa.util.xmlrpcprotocol import ServerException
+import sfa.util.xmlrpcprotocol as xmlrpcprotocol
 from sfa.util.config import Config
 
 class Sfi:
@@ -89,10 +89,15 @@ class Sfi:
        # Get key and certificate
        key_file = self.get_key_file()
        cert_file = self.get_cert_file(key_file)
-    
+       self.key = Keypair(filename=key_file) 
+       self.key_file = key_file
+       self.cert_file = cert_file
+       self.cert = Certificate(filename=cert_file) 
        # Establish connection to server(s)
-       self.slicemgr = GeniClient(sm_url, key_file, cert_file, self.options.protocol)
-       self.registry = GeniClient(reg_url, key_file, cert_file, self.options.protocol)
+       #self.slicemgr = GeniClient(sm_url, key_file, cert_file, self.options.protocol)
+       #self.registry = GeniClient(reg_url, key_file, cert_file, self.options.protocol)
+       self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file)  
+       self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file)  
        return
     
     #
@@ -136,23 +141,41 @@ class Sfi:
              print "Writing self-signed certificate to", file
           cert.save_to_file(file)
           return file
-    
+   
+    def get_gid(self):
+        file = os.path.join(self.options.sfi_dir, self.get_leaf(self.user) + ".gid")
+        if (os.path.isfile(file)):
+            gid = GID(filename=file)
+            return gid
+        else:
+            cert_str = self.cert.save_to_string(save_parents=True)
+            request_hash = self.key.compute_hash([cert_str, self.user, "user"])
+            gid_str = self.registry.get_gid(cert_str, self.user, "user", request_hash)
+            gid = GID(string=gid_str)
+            if self.options.verbose:
+                print "Writing user gid to", file
+            gid.save_to_file(file, save_parents=True)
+            return gid       
     def get_user_cred(self):
-       file = os.path.join(self.options.sfi_dir, self.get_leaf(self.user) + ".cred")
-       if (os.path.isfile(file)):
-          user_cred = Credential(filename=file)
-          return user_cred
-       else:
-          # bootstrap user credential
-          user_cred = self.registry.get_credential(None, "user", self.user)
-          if user_cred:
-             user_cred.save_to_file(file, save_parents=True)
-             if self.options.verbose:
-                print "Writing user credential to", file
-             return user_cred
-          else:
-             print "Failed to get user credential"
-             sys.exit(-1)
+        file = os.path.join(self.options.sfi_dir, self.get_leaf(self.user) + ".cred")
+        if (os.path.isfile(file)):
+            user_cred = Credential(filename=file)
+            return user_cred
+        else:
+            # bootstrap user credential
+            cert_string = self.cert.save_to_string(save_parents=True)
+            request_hash = self.key.compute_hash([cert_string, "user", self.user])
+            user_cred = self.registry.get_self_credential(cert_string, "user", self.user, request_hash)
+            if user_cred:
+               cred = Credential(string=user_cred)
+               cred.save_to_file(file, save_parents=True)
+               if self.options.verbose:
+                    print "Writing user credential to", file
+               return cred
+            else:
+               print "Failed to get user credential"
+               sys.exit(-1)
     
     def get_auth_cred(self):
     
@@ -166,13 +189,15 @@ class Sfi:
           return auth_cred
        else:
           # bootstrap authority credential from user credential
-          user_cred = self.get_user_cred()
-          auth_cred = self.registry.get_credential(user_cred, "authority", self.authority)
+          user_cred = self.get_user_cred().save_to_string(save_parents=True)
+          request_hash = self.key.compute_hash([user_cred, "authority", self.authority])
+          auth_cred = self.registry.get_credential(user_cred, "authority", self.authority, request_hash)
           if auth_cred:
-             auth_cred.save_to_file(file, save_parents=True)
+             cred = Credential(string=auth_cred)
+             cred.save_to_file(file, save_parents=True)
              if self.options.verbose:
                 print "Writing authority credential to", file
-             return auth_cred
+             return cred
           else:
              print "Failed to get authority credential"
              sys.exit(-1)
@@ -184,9 +209,12 @@ class Sfi:
           return slice_cred
        else:
           # bootstrap slice credential from user credential
-          user_cred = self.get_user_cred()
-          slice_cred = self.registry.get_credential(user_cred, "slice", name)
+          user_cred = self.get_user_cred().save_to_string(save_parents=True)
+          arg_list = [user_cred, "slice", name]
+          request_hash = self.key.compute_hash(arg_list)  
+          slice_cred_str = self.registry.get_credential(user_cred, "slice", name, request_hash)
           if slice_cred:
+             slice_cred = Credential(string=slice_cred_str)
              slice_cred.save_to_file(file, save_parents=True)
              if self.options.verbose:
                 print "Writing slice credential to", file
@@ -271,11 +299,14 @@ class Sfi:
     # Generate sub-command parser
     #
     def create_cmd_parser(self,command, additional_cmdargs = None):
-       cmdargs = {"list": "name",
+       cmdargs = {"gid": "",
+                  "list": "name",
                   "show": "name",
                   "remove": "name",
                   "add": "record",
                   "update": "record",
+                  "aggregates": "[name]",
+                  "registries": "[name]",   
                   "slices": "",
                   "resources": "[name]",
                   "create": "name rspec",
@@ -304,7 +335,13 @@ class Sfi:
            parser.add_option("-f", "--format", dest="format",type="choice",
                              help="display format ([xml]|dns|ip)",default="xml",
                              choices=("xml","dns","ip"))
-
+           parser.add_option("-a", "--aggregate", dest="aggregate",
+                             default=None, help="aggregate hrn")  
+    
+       if command in ("create"):
+           parser.add_option("-a", "--aggregate", dest="aggregate",default=None,
+                             help="aggregate hrn") 
        if command in ("list", "show", "remove"):
           parser.add_option("-t", "--type", dest="type",type="choice",
                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
@@ -332,7 +369,7 @@ class Sfi:
 
        # Generate command line parser
        parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
-                             description="Commands: list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
+                             description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
        parser.add_option("-r", "--registry", dest="registry",
                          help="root registry", metavar="URL", default=None)
        parser.add_option("-s", "--slicemgr", dest="sm",
@@ -363,12 +400,19 @@ class Sfi:
     #
     # Registry-related commands
     #
-    
+   
+    def gid(self, opts, args):
+       gid = self.get_gid()
+       print "GID: %s" % (gid.save_to_string(save_parents=True))
+       return   
     # list entires in named authority registry
     def list(self,opts, args):
-       user_cred = self.get_user_cred()
+       user_cred = self.get_user_cred().save_to_string(save_parents=True)
+       hrn = args[0]
+       request_hash = self.key.compute_hash([user_cred, hrn])    
        try:
-          list = self.registry.list(user_cred, args[0])
+          list = self.registry.list(user_cred, hrn, request_hash)
        except IndexError:
           raise Exception, "Not enough parameters for the 'list' command"
           
@@ -383,8 +427,10 @@ class Sfi:
     
     # show named registry record
     def show(self,opts, args):
-       user_cred = self.get_user_cred()
-       records = self.registry.resolve(user_cred, args[0])
+       user_cred = self.get_user_cred().save_to_string(save_parents=True)
+       hrn = args[0]
+       request_hash = self.key.compute_hash([user_cred, hrn])    
+       records = self.registry.resolve(user_cred, hrn, request_hash)
        records = self.filter_records(opts.type, records)
        if not records:
           print "No record of type", opts.type
@@ -466,45 +512,79 @@ class Sfi:
     # removed named registry record
     #   - have to first retrieve the record to be removed
     def remove(self,opts, args):
-       auth_cred = self.get_auth_cred()
-       return self.registry.remove(auth_cred, opts.type, args[0])
+       auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
+       hrn = args[0]
+       type = opts.type 
+       if type in ['all']:
+           type = '*'
+       arg_list = [auth_cred, type, hrn]
+       request_hash = self.key.compute_hash(arg_list)                   
+       return self.registry.remove(auth_cred, type, hrn, request_hash)
     
     # add named registry record
     def add(self,opts, args):
-       auth_cred = self.get_auth_cred()
-       rec_file = self.get_record_file(args[0])
-       record = self.load_record_from_file(rec_file)
-    
-       return self.registry.register(auth_cred, record)
+       auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
+       record_filepath = args[0]
+       rec_file = self.get_record_file(record_filepath)
+       record = self.load_record_from_file(rec_file).as_dict()
+       arg_list = [auth_cred]
+       request_hash = self.key.compute_hash(arg_list)
+       return self.registry.register(auth_cred, record, request_hash)
     
     # update named registry entry
     def update(self,opts, args):
        user_cred = self.get_user_cred()
        rec_file = self.get_record_file(args[0])
        record = self.load_record_from_file(rec_file)
-       if record.get_type() == "user":
+       if record['type'] == "user":
            if record.get_name() == user_cred.get_gid_object().get_hrn():
-              cred = user_cred
+              cred = user_cred.save_to_string(save_parents=True)
            else:
-              cred = self.get_auth_cred()
-       elif record.get_type() in ["slice"]:
+              cred = self.get_auth_cred().save_to_string(save_parents=True)
+       elif record['type'] in ["slice"]:
            try:
-               cred = self.get_slice_cred(record.get_name())
+               cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
            except ServerException, e:
                # XXX smbaker -- once we have better error return codes, update this
                # to do something better than a string compare
                if "Permission error" in e.args[0]:
-                   cred = self.get_auth_cred()
+                   cred = self.get_auth_cred().save_to_string(save_parents=True)
                else:
                    raise
        elif record.get_type() in ["authority"]:
-           cred = self.get_auth_cred()
+           cred = self.get_auth_cred().save_to_string(save_parents=True)
        elif record.get_type() == 'node':
-            cred = self.get_auth_cred()
+           cred = self.get_auth_cred().save_to_string(save_parents=True)
        else:
            raise "unknown record type" + record.get_type()
-       return self.registry.update(cred, record)
-    
+       record = record.as_dict()
+       arg_list = [cred]  
+       request_hash = self.key.compute_hash(arg_list)
+       return self.registry.update(cred, record, request_hash)
+   
+    
+    def aggregates(self, opts, args):
+        user_cred = self.get_user_cred().save_to_string(save_parents=True)
+        hrn = None
+        if args: 
+            hrn = args[0]
+        arg_list = [user_cred, hrn]  
+        request_hash = self.key.compute_hash(arg_list)
+        result = self.registry.get_aggregates(user_cred, hrn, request_hash)
+        self.display_list(result)
+        return 
+
+    def registries(self, opts, args):
+        user_cred = self.get_user_cred().save_to_string(save_parents=True)
+        hrn = None
+        if args:
+            hrn = args[0]
+        arg_list = [user_cred, hrn]  
+        request_hash = self.key.compute_hash(arg_list)
+        result = self.registry.get_registries(user_cred, hrn, request_hash)
+        self.display_list(result)
+        return
     #
     # Slice-related commands
     #
@@ -513,57 +593,94 @@ class Sfi:
 
     # list instantiated slices
     def slices(self,opts, args):
-       user_cred = self.get_user_cred()
-       results = self.slicemgr.get_slices(user_cred)
-       self.display_list(results)
-       return
+        user_cred = self.get_user_cred().save_to_string(save_parents=True)
+        arg_list = [user_cred]
+        request_hash = self.key.compute_hash(arg_list)
+        results = self.slicemgr.get_slices(user_cred, request_hash)
+        self.display_list(results)
+        return
     
     # show rspec for named slice
     def resources(self,opts, args):
-       if args:
-           slice_cred = self.get_slice_cred(args[0])
-           result = self.slicemgr.get_resources(slice_cred, args[0])
-       else:
-           user_cred = self.get_user_cred()
-           result = self.slicemgr.get_resources(user_cred)
-       format = opts.format      
-       self.display_rspec(result, format)
-       if (opts.file is not None):
-          self.save_rspec_to_file(result, opts.file)
-       return
+        user_cred = self.get_user_cred().save_to_string(save_parents=True)
+        server = self.slicemgr
+        if opts.aggregate:
+            agg_hrn = opts.aggregate
+            arg_list = [user_cred, arg_hrn]
+            request_hash = self.key.compute_hash(arg_list)
+            aggregates = self.registry.get_aggregates(user_cred, agg_hrn, request_hash)
+            if not aggregates:
+                raise Exception, "No such aggregate %s" % agg_hrn
+            aggregate = aggregates[0]
+            url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
+            server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
+        if args:
+            cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
+            hrn = args[0]
+        else:
+            cred = user_cred
+            hrn = None
+
+        arg_list = [cred, hrn]
+        request_hash = self.key.compute_hash(arg_list)  
+        result = server.get_resources(cred, hrn, request_hash)
+        format = opts.format
+       
+        self.display_rspec(result, format)
+        if (opts.file is not None):
+            self.save_rspec_to_file(result, opts.file)
+        return
     
     # created named slice with given rspec
     def create(self,opts, args):
        slice_hrn = args[0]
-       slice_cred = self.get_slice_cred(slice_hrn)
+       user_cred = self.get_user_cred()
+       slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
        rspec_file = self.get_rspec_file(args[1])
        rspec=open(rspec_file).read()
-       return self.slicemgr.create_slice(slice_cred, slice_hrn, rspec)
+       server = self.slicemgr
+       if opts.aggregate:
+           aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
+           if not aggregates:
+               raise Exception, "No such aggregate %s" % opts.aggregate
+           aggregate = aggregates[0]
+           url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
+           server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
+       arg_list = [slice_cred, slice_hrn, rspec]
+       request_hash = self.key.compute_hash(arg_list) 
+       return server.create_slice(slice_cred, slice_hrn, rspec, request_hash)
     
     # delete named slice
     def delete(self,opts, args):
-       slice_hrn = args[0]
-       slice_cred = self.get_slice_cred(slice_hrn)
-       
-       return self.slicemgr.delete_slice(slice_cred, slice_hrn)
+        slice_hrn = args[0]
+        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
+        arg_list = [slice_cred, slice_hrn]
+        request_hash = self.key.compute_hash(arg_list) 
+        return self.slicemgr.delete_slice(slice_cred, slice_hrn, request_hash)
     
     # start named slice
     def start(self,opts, args):
-       slice_hrn = args[0]
-       slice_cred = self.get_slice_cred(args[0])
-       return self.slicemgr.start_slice(slice_cred, slice_hrn)
+        slice_hrn = args[0]
+        slice_cred = self.get_slice_cred(args[0])
+        arg_list = [slice_cred, slice_hrn]
+        request_hash = self.key.compute_hash(arg_list)
+        return self.slicemgr.start_slice(slice_cred, slice_hrn, request_hash)
     
     # stop named slice
     def stop(self,opts, args):
-       slice_hrn = args[0]
-       slice_cred = self.get_slice_cred(args[0])
-       return self.slicemgr.stop_slice(slice_cred, slice_hrn)
+        slice_hrn = args[0]
+        slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
+        arg_list = [slice_cred, slice_hrn]
+        request_hash = self.key.compute_hash(arg_list)
+        return self.slicemgr.stop_slice(slice_cred, slice_hrn, request_hash)
     
     # reset named slice
     def reset(self,opts, args):
-       slice_hrn = args[0]
-       slice_cred = self.get_slice_cred(args[0])
-       return self.slicemgr.reset_slice(slice_cred, slice_hrn)
+        slice_hrn = args[0]
+        slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
+        arg_list = [slice_cred, slice_hrn]
+        request_hash = self.key.compute_hash(arg_list)
+        return self.slicemgr.reset_slice(slice_cred, slice_hrn, request_hash)
     
     #
     #
@@ -574,7 +691,7 @@ class Sfi:
     
     def display_rspec(self,rspec, format = 'rspec'):
         if format in ['dns']:
-            spec = Rspec()
+            spec = RSpec()
             spec.parseString(rspec)
             hostnames = []
             nodespecs = spec.getDictsByTagName('NodeSpec')
@@ -586,7 +703,7 @@ class Sfi:
                         hostnames.append(nodespec['name'])
             result = hostnames
         elif format in ['ip']:
-            spec = Rspec()
+            spec = RSpec()
             spec.parseString(rspec)
             ips = []
             ifspecs = spec.getDictsByTagName('IfSpec')
@@ -631,7 +748,7 @@ class Sfi:
     def filter_records(self,type, records):
        filtered_records = []
        for record in records:
-           if (record.get_type() == type) or (type == "all"):
+           if (record['type'] == type) or (type == "all"):
                filtered_records.append(record)
        return filtered_records
     
@@ -645,6 +762,16 @@ class Sfi:
            index = index + 1
     
     def save_record_to_file(self,filename, record):
+       if record['type'] in ['user']:
+           record = UserRecord(dict = record)
+       elif record['type'] in ['slice']:
+           record = SliceRecord(dict = record)
+       elif record['type'] in ['node']:
+           record = NodeRecord(dict = record)
+       elif record['type'] in ['authority', 'ma', 'sa']:
+          record = AuthorityRecord(dict = record)
+       else:
+           record = GeniRecord(dict = record) 
        if not filename.startswith(os.sep):
            filename = self.options.sfi_dir + filename
        str = record.save_to_string()
@@ -660,7 +787,6 @@ class Sfi:
     # Main: parse arguments and dispatch to command
     #
     def main(self):
-    
        parser = self.create_parser()
        (options, args) = parser.parse_args()
        self.options = options