using method get_self_credential to bootstrap SM credential
[sfa.git] / sfa / plc / api.py
index fefb5bf..5af31ec 100644 (file)
@@ -17,7 +17,10 @@ from sfa.util.faults import *
 from sfa.util.debug import *
 from sfa.trust.rights import *
 from sfa.trust.credential import *
+from sfa.trust.certificate import *
 from sfa.util.misc import *
+from sfa.util.sfalogging import *
+from sfa.util.genitable import *
 
 # See "2.2 Characters" in the XML specification:
 #
@@ -113,29 +116,35 @@ class GeniAPI:
         self.auth = Auth(peer_cert)
         self.interface = interface
         self.key_file = key_file
+        self.key = Keypair(filename=self.key_file)
         self.cert_file = cert_file
+        self.cert = Certificate(filename=self.cert_file)
         self.credential = None
-        self.plshell = self.getPLCShell()
-        self.plshell_version = self.getPLCShellVersion()
-        self.basedir = self.config.SFA_BASE_DIR + os.sep
-        self.server_basedir = self.basedir + os.sep + "geni" + os.sep
+        
+        # Initialize the PLC shell only if SFA wraps a myPLC
+        rspec_type = self.config.get_aggregate_rspec_type()
+        if (rspec_type == 'pl' or rspec_type == 'vini'):
+            self.plshell = self.getPLCShell()
+            self.plshell_version = self.getPLCShellVersion()
+
         self.hrn = self.config.SFA_INTERFACE_HRN
         self.time_format = "%Y-%m-%d %H:%M:%S"
-
+        self.logger=get_sfa_logger()
 
     def getPLCShell(self):
         self.plauth = {'Username': self.config.SFA_PLC_USER,
                        'AuthMethod': 'password',
                        'AuthString': self.config.SFA_PLC_PASSWORD}
         try:
+            self.plshell_type = 'direct'
             import PLC.Shell
             shell = PLC.Shell.Shell(globals = globals())
             shell.AuthCheck(self.plauth)
             return shell
         except ImportError:
+            self.plshell_type = 'xmlrpc' 
             # connect via xmlrpc
             url = self.config.SFA_PLC_URL
-             
             shell = xmlrpclib.Server(url, verbose = 0, allow_none = True)
             shell.AuthCheck(self.plauth)
             return shell
@@ -161,25 +170,33 @@ class GeniAPI:
         else:
             return self.getCredentialFromRegistry()
     
-
     def getCredentialFromRegistry(self):
         """ 
         Get our credential from a remote registry using a geniclient connection
         """
         type = 'authority'
-        path = self.config.config_path
+        path = self.config.SFA_BASE_DIR
         filename = ".".join([self.interface, self.hrn, type, "cred"])
         cred_filename = path + os.sep + filename
         try:
             credential = Credential(filename = cred_filename)
-            return credential
+            return credential.save_to_string(save_parents=True)
         except IOError:
             from sfa.server.registry import Registries
             registries = Registries(self)
             registry = registries[self.hrn]
-            self_cred = registry.get_credential(None, type, self.hrn)
-            cred = registry.get_credential(self_cred, type, self.hrn)
-            cred.save_to_file(cred_filename, save_parents=True)
+           cert_string=self.cert.save_to_string(save_parents=True)
+            # get self credential
+            arg_list = [cert_string,type,self.hrn]
+            request_hash=self.key.compute_hash(arg_list)
+            self_cred = registry.get_self_credential(cert_string, type, self.hrn, request_hash)
+            # get credential
+            arg_list = [self_cred,type,self.hrn]
+            request_hash=self.key.compute_hash(arg_list)
+            cred = registry.get_credential(self_cred, type, self.hrn, request_hash)
+            
+            # save cred to file
+            Credential(string=cred).save_to_file(cred_filename, save_parents=True)
             return cred
 
     def getCredentialFromLocalRegistry(self):
@@ -189,15 +206,17 @@ class GeniAPI:
 
         hrn = self.hrn
         auth_hrn = self.auth.get_authority(hrn)
-        if not auth_hrn:
+    
+        # is this a root or sub authority
+        if not auth_hrn or hrn == self.config.SFA_INTERFACE_HRN:
             auth_hrn = hrn
         auth_info = self.auth.get_auth_info(auth_hrn)
-        table = self.auth.get_auth_table(auth_hrn)
-        records = table.resolve('*', hrn)
+        table = GeniTable()
+        records = table.findObjects(hrn)
         if not records:
             raise RecordNotFound
         record = records[0]
-        type = record.get_type()
+        type = record['type']
         object_gid = record.get_gid_object()
         new_cred = Credential(subject = object_gid.get_subject())
         new_cred.set_gid_caller(object_gid)
@@ -214,7 +233,7 @@ class GeniAPI:
         new_cred.encode()
         new_cred.sign()
 
-        return new_cred
+        return new_cred.save_to_string(save_parents=True)
    
 
     def loadCredential (self):
@@ -226,7 +245,7 @@ class GeniAPI:
         # see if this file exists
         # XX This is really the aggregate's credential. Using this is easier than getting
         # the registry's credential from iteslf (ssl errors).   
-        ma_cred_filename = self.server_basedir + os.sep + self.interface + self.hrn + ".ma.cred"
+        ma_cred_filename = self.config.SFA_BASE_DIR + os.sep + self.interface + self.hrn + ".ma.cred"
         try:
             self.credential = Credential(filename = ma_cred_filename)
         except IOError:
@@ -263,9 +282,9 @@ class GeniAPI:
 
         elif type == "node":
             if not "hostname" in pl_record:
-                if not "dns" in record:
-                    raise MissingGeniInfo("dns")
-                pl_record["hostname"] = record["dns"]
+                if not "hostname" in record:
+                    raise MissingGeniInfo("hostname")
+                pl_record["hostname"] = record["hostname"]
             if not "model" in pl_record:
                 pl_record["model"] = "geni"
 
@@ -296,8 +315,8 @@ class GeniAPI:
     
         @param record: record to fill in field (in/out param)     
         """
-        type = record.get_type()
-        pointer = record.get_pointer()
+        type = record['type']
+        pointer = record['pointer']
         auth_hrn = self.hrn
         login_base = ''
         # records with pointer==-1 do not have plc info associated with them.
@@ -307,7 +326,7 @@ class GeniAPI:
             record.update({})
             return
 
-        if (type in ["authority", "sa", "ma"]):
+        if (type in ["authority"]):
             pl_res = self.plshell.GetSites(self.plauth, [pointer])
         elif (type == "slice"):
             pl_res = self.plshell.GetSlices(self.plauth, [pointer])
@@ -319,7 +338,7 @@ class GeniAPI:
             raise UnknownGeniType(type)
         
         if not pl_res:
-            raise PlanetLabRecordDoesNotExist(record.get_name())
+            raise PlanetLabRecordDoesNotExist(record['hrn'])
 
         # convert ids to hrns
         pl_record = pl_res[0]
@@ -359,35 +378,42 @@ class GeniAPI:
         record.update(pl_record)
 
 
-    def lookup_users(self, auth_table, user_id_list, role="*"):
-        record_list = []
-        for person_id in user_id_list:
-            user_records = auth_table.find("user", person_id, "pointer")
-            for user_record in user_records:
-                self.fill_record_info(user_record)
-                user_roles = user_record.get("roles")
-                if (role=="*") or (role in user_roles):
-                    record_list.append(user_record.get_name())
-        return record_list
 
     def fill_record_geni_info(self, record):
         geni_info = {}
-        type = record.get_type()
+        type = record['type']
+        table = GeniTable()
         if (type == "slice"):
-            auth_table = self.auth.get_auth_table(self.auth.get_authority(record.get_name()))
             person_ids = record.get("person_ids", [])
-            researchers = self.lookup_users(auth_table, person_ids)
+            persons = table.find({'type': 'user', 'pointer': person_ids})
+            researchers = [person['hrn'] for person in persons]
             geni_info['researcher'] = researchers
 
         elif (type == "authority"):
-            auth_table = self.auth.get_auth_table(record.get_name())
             person_ids = record.get("person_ids", [])
-            pis = self.lookup_users(auth_table, person_ids, "pi")
-            operators = self.lookup_users(auth_table, person_ids, "tech")
-            owners = self.lookup_users(auth_table, person_ids, "admin")
-            geni_info['pi'] = pis
-            geni_info['operator'] = operators
-            geni_info['owner'] = owners
+            persons = table.find({'type': 'user', 'pointer': person_ids})
+            persons_dict = {}
+            for person in persons:
+                persons_dict[person['pointer']] = person 
+            pl_persons = self.plshell.GetPersons(self.plauth, person_ids, ['person_id', 'roles'])
+            pis, techs, admins = [], [], []
+            for person in pl_persons:
+                pointer = person['person_id']
+                
+                if pointer not in persons_dict:
+                    # this means there is not sfa record for this user
+                    continue    
+                hrn = persons_dict[pointer]['hrn']    
+                if 'pi' in person['roles']:
+                    pis.append(hrn)
+                if 'tech' in person['roles']:
+                    techs.append(hrn)
+                if 'admin' in person['roles']:
+                    admins.append(hrn)
+            
+            geni_info['PI'] = pis
+            geni_info['operator'] = techs
+            geni_info['owner'] = admins
             # xxx TODO: OrganizationName
 
         elif (type == "node"):
@@ -423,16 +449,10 @@ class GeniAPI:
         # build a list of the new person ids, by looking up each person to get
         # their pointer
         newIdList = []
-        for hrn in newList:
-            auth_hrn = self.auth.get_authority(hrn)
-            if not auth_hrn:
-                auth_hrn = hrn
-            auth_info = self.auth.get_auth_info(auth_hrn)
-            table = self.auth.get_auth_table(auth_hrn)
-            records = table.resolve('user', hrn)
-            if records:
-                userRecord = records[0]    
-                newIdList.append(userRecord.get_pointer())
+        table = GeniTable()
+        records = table.find({'type': 'user', 'hrn': newList})
+        for rec in records:
+            newIdList.append(rec['pointer'])
 
         # build a list of the old person ids from the person_ids field 
         if oldRecord:
@@ -447,13 +467,11 @@ class GeniAPI:
     # add people who are in the new list, but not the oldList
         for personId in newIdList:
             if not (personId in oldIdList):
-                print "adding id", personId, "to", record.get_name()
                 addFunc(self.plauth, personId, containerId)
 
         # remove people who are in the old list, but not the new list
         for personId in oldIdList:
             if not (personId in newIdList):
-                print "removing id", personId, "from", record.get_name()
                 delFunc(self.plauth, personId, containerId)
 
     def update_membership(self, oldRecord, record):
@@ -497,7 +515,6 @@ class GeniAPI:
         """
         Handle an XML-RPC or SOAP request from the specified source.
         """
-
         # Parse request into method name and arguments
         try:
             interface = xmlrpclib
@@ -537,3 +554,4 @@ class GeniAPI:
             data = buildSOAP(kw = {'%sResponse' % method: {'Result': result}}, encoding = self.encoding)
 
         return data
+