removed all refrences to pl_info/geni_info in record object and anything that used...
authorTony Mack <tmack@cs.princeton.edu>
Thu, 4 Jun 2009 02:31:37 +0000 (02:31 +0000)
committerTony Mack <tmack@cs.princeton.edu>
Thu, 4 Jun 2009 02:31:37 +0000 (02:31 +0000)
geni/methods/register.py
geni/methods/update.py
geni/util/api.py
geni/util/auth.py
geni/util/geniclient.py
geni/util/genitable.py
geni/util/record.py
geni/util/slices.py

index f8b5860..47924be 100644 (file)
@@ -44,8 +44,8 @@ class register(Method):
         if existing_records:
             raise ExistingRecord(name)
 
-        geni_fields = record.get_geni_info()
-        pl_fields = record.get_pl_info()
+        geni_fields = record.as_dict()
+        pl_fields = record.as_dict()
         
         if (type == "sa") or (type=="ma"):
             # update the tree
index 1f2788d..a62d38b 100644 (file)
@@ -12,12 +12,6 @@ class update(Method):
     PLC information associated with the record. The Geni fields (name, type,
     GID) are fixed.
     
-    The record is expected to have the pl_info field filled in with the data
-    that should be updated.
-    
-    TODO: The geni_info member of the record should be parsed and the pl_info
-    adjusted as necessary (add/remove users from a slice, etc)
-    
     @param cred credential string specifying rights of the caller
     @param record a record dictionary to be updated
 
@@ -60,17 +54,17 @@ class update(Method):
         # update the PLC information that was specified with the record
 
         if (type == "authority"):
-            self.api.plshell.UpdateSite(self.api.plauth, pointer, record.get_pl_info())
+            self.api.plshell.UpdateSite(self.api.plauth, pointer, record)
 
         elif type == "slice":
-            self.api.plshell.UpdateSlice(self.api.plauth, pointer, record.get_pl_info())
+            self.api.plshell.UpdateSlice(self.api.plauth, pointer, record)
 
         elif type == "user":
             # SMBAKER: UpdatePerson only allows a limited set of fields to be
             #    updated. Ideally we should have a more generic way of doing
             #    this. I copied the field names from UpdatePerson.py...
             update_fields = {}
-            all_fields = record.get_pl_info()
+            all_fields = record
             for key in all_fields.keys():
                 if key in ['first_name', 'last_name', 'title', 'email',
                            'password', 'phone', 'url', 'bio', 'accepted_aup',
@@ -79,7 +73,7 @@ class update(Method):
             self.api.plshell.UpdatePerson(self.api.plauth, pointer, update_fields)
 
         elif type == "node":
-            self.api.plshell.UpdateNode(self.api.plauth, pointer, record.get_pl_info())
+            self.api.plshell.UpdateNode(self.api.plauth, pointer, record)
 
         else:
             raise UnknownGeniType(type)
index ce08972..228647f 100644 (file)
@@ -305,7 +305,7 @@ class GeniAPI:
         # for example, the top level authority records which are
         # authorities, but not PL "sites"
         if pointer == -1:
-            record.set_pl_info({})
+            record.update({})
             return
 
         if (type in ["authority", "sa", "ma"]):
@@ -357,7 +357,7 @@ class GeniAPI:
                 pubkeys = [key['key'] for key in keys]
             pl_record['keys'] = pubkeys     
 
-        record.set_pl_info(pl_record)
+        record.update(pl_record)
 
 
     def lookup_users(self, auth_table, user_id_list, role="*"):
@@ -367,7 +367,7 @@ class GeniAPI:
             for user_record in user_records:
                 self.fill_record_info(user_record)
 
-                user_roles = user_record.get_pl_info().get("roles")
+                user_roles = user_record.get("roles")
                 if (role=="*") or (role in user_roles):
                     record_list.append(user_record.get_name())
         return record_list
@@ -378,13 +378,13 @@ class GeniAPI:
 
         if (type == "slice"):
             auth_table = self.auth.get_auth_table(self.auth.get_authority(record.get_name()))
-            person_ids = record.pl_info.get("person_ids", [])
+            person_ids = record.get("person_ids", [])
             researchers = self.lookup_users(auth_table, person_ids)
             geni_info['researcher'] = researchers
 
         elif (type == "authority"):
             auth_table = self.auth.get_auth_table(record.get_name())
-            person_ids = record.pl_info.get("person_ids", [])
+            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")
@@ -394,14 +394,14 @@ class GeniAPI:
             # TODO: OrganizationName
 
         elif (type == "node"):
-            geni_info['dns'] = record.pl_info.get("hostname", "")
+            geni_info['dns'] = record.get("hostname", "")
             # TODO: URI, LatLong, IP, DNS
     
         elif (type == "user"):
-            geni_info['email'] = record.pl_info.get("email", "")
+            geni_info['email'] = record.get("email", "")
             # TODO: PostalAddress, Phone
 
-        record.set_geni_info(geni_info)
+        record.update(geni_info)
 
     def fill_record_info(self, record):
         """
@@ -413,13 +413,8 @@ class GeniAPI:
 
     def update_membership_list(self, oldRecord, record, listName, addFunc, delFunc):
         # get a list of the HRNs tht are members of the old and new records^M
-        if oldRecord:
-            if oldRecord.pl_info == None:
-                oldRecord.pl_info = {}
-            oldList = oldRecord.get_geni_info().get(listName, [])
-        else:
-            oldList = []
-        newList = record.get_geni_info().get(listName, [])
+        oldList = oldRecord.get(listName, [])
+        newList = record.get(listName, [])
 
         # if the lists are the same, then we don't have to update anything
         if (oldList == newList):
@@ -440,9 +435,8 @@ class GeniAPI:
                 newIdList.append(userRecord.get_pointer())
 
         # build a list of the old person ids from the person_ids field of the
-        # pl_info
         if oldRecord:
-            oldIdList = oldRecord.pl_info.get("person_ids", [])
+            oldIdList = oldRecord.get("person_ids", [])
             containerId = oldRecord.get_pointer()
         else:
             # if oldRecord==None, then we are doing a Register, instead of an
index 442ce20..f190432 100644 (file)
@@ -168,7 +168,7 @@ class Auth:
         rl = RightList()
 
         if type=="slice":
-            researchers = record.get_geni_info().get("researcher", [])
+            researchers = record.get("researcher", [])
             if (cred_object_hrn in researchers):
                 rl.add("refresh")
                 rl.add("embed")
@@ -177,8 +177,8 @@ class Auth:
                 rl.add("info")
 
         elif type == "authority":
-            pis = record.get_geni_info().get("pi", [])
-            operators = record.get_geni_info().get("operator", [])
+            pis = record.get("pi", [])
+            operators = record.get("operator", [])
             rl.add("authority,sa,ma")
             if (cred_object_hrn in pis):
                 rl.add("sa")
@@ -204,15 +204,15 @@ class Auth:
         if cred_object_hrn in [self.config.GENI_REGISTRY_ROOT_AUTH]:
             return
         if type=="slice":
-            researchers = record.get_geni_info().get("researcher", [])
+            researchers = record.get("researcher", [])
             if not (cred_object_hrn in researchers):
                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
         elif type == "sa":
-            pis = record.get_geni_info().get("pi", [])
+            pis = record.get("pi", [])
             if not (cred_object_hrn in pis):
                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
         elif type == "ma":
-            operators = record.get_geni_info().get("operator", [])
+            operators = record.get("operator", [])
             if not (cred_object_hrn in operators):
                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
 
index 4571fa8..316cc57 100644 (file)
@@ -177,11 +177,7 @@ class GeniClient():
     # Geni database, the appropriate records will also be created in the
     # PLC databases.
     #
-    # The geni_info and/or pl_info fields must in the record must be filled
-    # out correctly depending on the type of record that is being registered.
     #
-    # TODO: The geni_info member of the record should be parsed and the pl_info
-    # adjusted as necessary (add/remove users from a slice, etc)
     #
     # @param cred credential object specifying rights of the caller
     # @return record to register
@@ -217,7 +213,16 @@ class GeniClient():
         result_dict_list = self.server.resolve(cred.save_to_string(save_parents=True), name)
         result_rec_list = []
         for dict in result_dict_list:
-             result_rec_list.append(GeniRecord(dict=dict))
+            if dict['type'] in ['authority']:
+                result_rec_list.append(AuthorityRecord(dict=dict))
+            elif dict['type'] in ['node']:
+                result_rec_list.append(NodeRecord(dict=dict))
+            elif dict['type'] in ['slice']:
+                result_rec_list.append(SliceRecord(dict=dict))
+            elif dict['type'] in ['user']:
+                result_rec_list.append(UserRecord(dict=dict))
+            else:
+                result_rec_list.append(GeniRecord(dict=dict))
         return result_rec_list
 
     ##
@@ -225,11 +230,7 @@ class GeniClient():
     # PLC information associated with the record. The Geni fields (name, type,
     # GID) are fixed.
     #
-    # The record is expected to have the pl_info field filled in with the data
-    # that should be updated.
     #
-    # TODO: The geni_info member of the record should be parsed and the pl_info
-    # adjusted as necessary (add/remove users from a slice, etc)
     #
     # @param cred credential object specifying rights of the caller
     # @param record a record object to be updated
index ed9ca30..e6dd015 100644 (file)
@@ -92,14 +92,24 @@ class GeniTable():
         result_dict_list = []
         for dict in dict_list:
            if (type=="*") or (dict['type'] == type):
+               dict['hrn'] = dict['name'] 
                result_dict_list.append(dict)
         return result_dict_list
 
     def find(self, type, value, searchfield):
         result_dict_list = self.find_dict(type, value, searchfield)
         result_rec_list = []
-        for dict in result_dict_list:
-            result_rec_list.append(GeniRecord(dict=dict))
+        for result in result_dict_list:
+            if result['type'] in ['authority']:
+                result_rec_list.append(AuthorityRecord(dict=result))
+            elif result['type'] in ['node']:
+                result_rec_list.append(NodeRecord(dict=result))
+            elif result['type'] in ['slice']:
+                result_rec_list.append(SliceRecord(dict=result))
+            elif result['type'] in ['user']:
+                result_rec_list.append(UserRecord(dict=result))
+            else:
+                result_rec_list.append(GeniRecord(dict=result))
         return result_rec_list
 
     def resolve_dict(self, type, hrn):
@@ -117,7 +127,7 @@ class GeniTable():
         result_dict_list = self.list_dict()
         result_rec_list = []
         for dict in result_dict_list:
-            result_rec_list.append(GeniRecord(dict=dict))
+            result_rec_list.append(GeniRecord(dict=dict).as_dict())
         return result_rec_list
 
 def set_geni_table_prefix(x):
index 368f910..e237fce 100644 (file)
@@ -8,9 +8,9 @@ import report
 from types import StringTypes
 from gid import *
 from geni.util.rspec import *
+from geni.util.parameter import *
 
-
-class GeniRecord:
+class GeniRecord(dict):
     """ 
     The GeniRecord class implements a Geni Record. A GeniRecord is a tuple
     (Name, GID, Type, Info).
@@ -21,8 +21,6 @@ class GeniRecord:
  
     Info is comprised of the following sub-fields
            pointer = a pointer to the record in the PL database
-           pl_info = planetlab-specific info (when talking to client)
-           geni_info = geni-specific info (when talking to client)
  
     The pointer is interpreted depending on the type of the record. For example,
     if the type=="user", then pointer is assumed to be a person_id that indexes
@@ -32,6 +30,16 @@ class GeniRecord:
     of different types.
     """
 
+    fields = {
+        'hrn': Parameter(str, "Human readable name of object"),
+        'type': Parameter(str, "Record type"),
+        'gid': Parameter(str, "GID of the object")
+    }
+
+    internal_fields = {
+        'pointer': Parameter(int, "Internal ID")
+    }
+
     ##
     # Create a Geni Record
     #
@@ -43,8 +51,6 @@ class GeniRecord:
 
     def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None, string=None):
         self.dirty = True
-        self.pl_info = None
-        self.geni_info = None
         self.name = None
         self.gid = None
         self.type = None
@@ -62,6 +68,20 @@ class GeniRecord:
         if string:
             self.load_from_string(string)
 
+    
+    def update(self, new_dict):
+        if isinstance(new_dict, list):
+            new_dict = new_dict[0]
+
+        # Convert any boolean strings to real bools
+        for key in new_dict:
+            if isinstance(new_dict[key], StringTypes):
+                if new_dict[key].lower() in ["true"]:
+                    new_dict[key] = True
+                elif new_dict[key].lower() in ["false"]:
+                    new_dict[key] = False
+        dict.update(self, new_dict)
+
     ##
     # Set the name of the record
     #
@@ -114,66 +134,6 @@ class GeniRecord:
         self.pointer = pointer
         self.dirty = True
 
-    ##
-    # Set the PLC info of the record
-    #
-    # @param pl_info is a dictionary containing planetlab info
-
-    def set_pl_info(self, pl_info):
-        """
-        Set the PLC info of the record
-        """ 
-        if isinstance(pl_info, list):
-            pl_info = pl_info[0]
-        
-        # Convert any boolean strings to real bools
-        for key in pl_info:
-            if isinstance(pl_info[key], StringTypes):
-                if pl_info[key].lower() in ["true"]:
-                    pl_info[key] = True
-                elif pl_info[key].lower() in ["false"]:
-                    pl_info[key] = False   
-        self.pl_info = pl_info
-        self.dirty = True
-
-    ##
-    # Set the geni info the record
-    #
-    # @param geni_info is a dictionary containing geni info
-
-    def set_geni_info(self, geni_info):
-        """
-        Set the geni info the record
-        """
-        if isinstance(geni_info, list):
-            geni_info = geni_info[0]
-        self.geni_info = geni_info
-        self.dirty = True
-
-    ##
-    # Return the pl_info of the record, or an empty dictionary if none exists
-
-    def get_pl_info(self):
-        """
-        Return the pl_info of the record, or an empty dictionary if none exists
-        """
-        if self.pl_info:
-            return self.pl_info
-        else:
-            return {}
-
-    ##
-    # Return the geni_info of the record, or an empty dictionary if none exists
-
-    def get_geni_info(self):
-        """
-        Return the geni_info of the record, or an empty dictionary if none exists
-        """
-        if self.geni_info:
-            return self.geni_info
-        else:
-            return {}
-
     ##
     # Return the name (HRN) of the record
 
@@ -230,15 +190,11 @@ class GeniRecord:
         return self.name + "#" + self.type
 
     ##
-    # Returns a list of field names in this record. pl_info, geni_info are not
-    # included because they are not part of the record that is stored in the
-    # database, but are rather computed values from other entities
+    # Returns a list of field names in this record. 
 
     def get_field_names(self):
         """
-        Returns a list of field names in this record. pl_info, geni_info are not
-        included because they are not part of the record that is stored in the
-        database, but are rather computed values from other entities
+        Returns a list of field names in this record.
         """
         return ["name", "gid", "type", "pointer"]
 
@@ -281,18 +237,7 @@ class GeniRecord:
         """
         Return the record in the form of a dictionary
         """
-        dict = {}
-        names = self.get_field_names()
-        for name in names:
-            dict[name] = getattr(self, name)
-
-        if self.pl_info:
-            dict['pl_info'] = self.pl_info
-
-        if self.geni_info:
-            dict['geni_info'] = self.geni_info
-
-        return dict
+        return dict(self)
 
     ##
     # Load the record from a dictionary
@@ -308,14 +253,13 @@ class GeniRecord:
         if gidstr:
             self.set_gid(dict['gid'])
 
-        self.set_type(dict['type'])
         if "pointer" in dict:
            self.set_pointer(dict['pointer'])
-        if "pl_info" in dict and dict['pl_info']:
-           self.set_pl_info(dict["pl_info"])
-        if "geni_info" in dict and dict['geni_info']:
-           self.set_geni_info(dict["geni_info"])
 
+        self.set_type(dict['type'])
+        self['hrn'] = dict['name'] 
+        self.update(dict)        
+    
     ##
     # Save the record to a string. The string contains an XML representation of
     # the record.
@@ -358,37 +302,124 @@ class GeniRecord:
         """
         Walk tree and dump records.
         """
-        print "RECORD", self.name
-        print "        hrn:", self.name
-        print "       type:", self.type
-        print "        gid:"
-        if (not self.gid):
-            print "        None"
-        else:
-            self.get_gid_object().dump(8, dump_parents)
-        print "    pointer:", self.pointer
-
-        print "  geni_info:"
-        geni_info = getattr(self, "geni_info", {})
-        if geni_info:
-            for key in geni_info.keys():
-                print "       ", key, ":", geni_info[key]
-
-        print "    pl_info:"
-        pl_info = getattr(self, "pl_info", {})
-        if pl_info:
-
-            for key in (s for s in pl_info.keys()\
-            if (s.endswith("_ids") or s.endswith("_id")) == False):
-                print "       ", key, ":", pl_info[key]
-
-
+        #print "RECORD", self.name
+        #print "        hrn:", self.name
+        #print "       type:", self.type
+        #print "        gid:"
+        #if (not self.gid):
+        #    print "        None"
+        #else:
+        #    self.get_gid_object().dump(8, dump_parents)
+        #print "    pointer:", self.pointer
+       
+        order = GeniRecord.fields.keys() 
+        for key in self.keys():
+            if key not in order:
+                order.append(key)
+        for key in order:
+            if key in (self and self.fields):
+                if key in 'gid' and self[key]:
+                    gid = GID(string=self[key])
+                    print "     %s:" % key
+                    gid.dump(8, dump_parents)
+                else:    
+                    print "     %s: %s" % (key, self[key])
+    
     def getdict(self):
-        info = {'hrn': self.name, 'type': self.type, 'gid': self.gid}
-        geni_info = getattr(self, "geni_info", {})
-        pl_info = getattr(self, "pl_info", {}) 
-        if geni_info:
-            info.update(geni_info)
-        if pl_info:
-            info.update(pl_info)
-        return info
+        return dict(self)
+    
+
+class UserRecord(GeniRecord):
+
+    fields = {
+        'email': Parameter(str, 'email'),
+        'first_name': Parameter(str, 'First name'),
+        'last_name': Parameter(str, 'Last name'),
+        'title': Parameter(str, 'Title'),
+        'phone': Parameter(str, 'Phone Number'),
+        'sites': Parameter([str], 'List of sites this user belongs to'),
+        'slices': Parameter([str], 'List of slices this user belongs to'),
+        'keys': Parameter([str], 'Public keys'),
+        'enabled': Parameter(bool, 'Is this person enabled'),
+        'date_created': Parameter(int, 'Date and time this record was created'),
+        'last_updated': Parameter(int, 'Date and time of last update'),
+        }
+    fields.update(GeniRecord.fields)
+    internal_fields = {
+        'roles': Parameter([str], 'List of roles')             
+        }
+    internal_fields.update(GeniRecord.internal_fields)
+    
+class SliceRecord(GeniRecord):
+    fields = {
+        'name': Parameter(str, 'Slice name'),
+        'instantiation': Parameter(str, 'Slice instantiation'),
+        'url': Parameter(str, 'Slice url'),
+        'expires': Parameter(int, 'Date and time this slice exipres'),
+        'persons': Parameter([str], 'List of users for this slice'),
+        'nodes': Parameter([str], 'List of nodes this slice is instantiated on'),
+        'description': Parameter([str], 'Description of this slice'), 
+        'date_created': Parameter(int, 'Date and time this record was created'),
+        }
+    fields.update(GeniRecord.fields)
+
+    internal_fields = {
+        'site': Parameter(str, 'Site this slice belongs to'),
+        'max_nodes': Parameter(int, 'Maximum number of nodes this slice is allowed on')
+        }
+    internal_fields.update(GeniRecord.internal_fields)
+class NodeRecord(GeniRecord):
+    fields = {
+        'slices': Parameter([str], 'List of instantiated slices on this node'),
+        'hostname': Parameter(str, 'This nodes dns name'),
+        'boot_state': Parameter(str, 'This nodes boot state'),
+        'node_type': Parameter(str, 'Type of node this is'),
+        'last_updated': Parameter(int, 'Date and time of last update'),
+        'slice_ids_whitelist': Parameter([str], 'List of allowed slices on this node'),
+        'date_created': Parameter(int, 'Date and time this node record was created'),
+        }
+    fields.update(GeniRecord.fields)
+
+    internal_fields = {
+        'site': Parameter(str, 'Site this node belongs to'),
+        'session': Parameter(str, 'This nodes session key'),
+        'ssh_rsa_key': Parameter(str, 'Last known ssh host key'),
+        'verified': Parameter(str, 'Whether the node configuration is verified correct'),
+        'last_contact': Parameter(int, 'Date and time this node last phoned home'),
+        'run_level': Parameter(str, 'Run level'),
+        'version': Parameter(str, 'Node software version'),
+        'key': Parameter(str, 'Node key'),
+        'boot_noonce': Parameter(str, 'Random value generate at nodes last boot'),
+        'model': Parameter(str, 'Model of node'),
+        'ports': Parameter([int], 'List of pcu ports this node is connected to') 
+        }
+    internal_fields.update(GeniRecord.internal_fields)
+
+class AuthorityRecord(GeniRecord):
+    fields =  {
+        'operators': Parameter([str], 'List of operators'),
+        'owners': Parameter([str], 'List of owners'),
+        'last_updated': Parameter(int, 'Date and time this record was last updated'),
+        'date_created': Parameter(int, 'Date and time this record was created'),
+        'name': Parameter(str, 'Name'),
+        'abbreviated_name': Parameter(str, 'Abbreviated name'),
+        'login_base': Parameter(str, 'login base'),
+        'enabled': Parameter(bool, 'Is this site enabled'),
+        'url': Parameter(str, 'URL'),
+        'slices': Parameter([str], 'List of slices instantiated by this site'),
+        'nodes': Parameter([str], 'List of nodes at this site'),  
+        'latitude': Parameter(float, 'Decimal latitude of the site'),
+        'longitude': Parameter(float, 'Decimal longitude of the site'),    
+        }
+    fields.update(GeniRecord.fields)
+    
+    internal_fields = {
+        'max_slices': Parameter(int, 'Maximum number of slices this site can instantiate'),
+        'max_slivers': Parameter(int, 'Maximum number of slivers this site can instantiate'),
+        'pi': Parameter([str], 'List of pis'),
+        'is_public': Parameter(bool, 'Is this site public'),
+        
+        }
+    internal_fields.update(GeniRecord.internal_fields) 
index 7ca3eed..1ba2f95 100644 (file)
@@ -129,8 +129,7 @@ class Slices(SimpleStorage):
         records = registry.resolve(credential, hrn)
         for record in records:
             if record.get_type() in ['slice']:
-                slice_info = record.as_dict()
-                slice = slice_info['pl_info']
+                slice = record.as_dict()
         if not slice:
             raise RecordNotFound(slice_hrn)   
 
@@ -149,8 +148,7 @@ class Slices(SimpleStorage):
                 if not site_records:
                     raise RecordNotFound(authority)
                 site_record = site_records[0]
-                site_info = site_record.as_dict()
-                site = site_info['pl_info']
+                site = site_record.as_dict()
                 
                  # add the site
                 site.pop('site_id')
@@ -162,8 +160,7 @@ class Slices(SimpleStorage):
 
         # get the list of valid slice users from the registry and make 
         # they are added to the slice 
-        geni_info = slice_info['geni_info']
-        researchers = geni_info['researcher']
+        researchers = slice.get('researcher', [])
         for researcher in researchers:
             person_record = {}
             person_records = registry.resolve(credential, researcher)
@@ -172,7 +169,7 @@ class Slices(SimpleStorage):
                     person_record = record
             if not person_record:
                 pass
-            person_dict = person_record.as_dict()['pl_info']
+            person_dict = person_record.as_dict()
             persons = self.api.plshell.GetPersons(self.api.plauth, [person_dict['email']], ['person_id', 'key_ids'])
 
             # Create the person record