rename attributes to slice_attribute_types
authorMark Huang <mlhuang@cs.princeton.edu>
Mon, 16 Oct 2006 21:59:05 +0000 (21:59 +0000)
committerMark Huang <mlhuang@cs.princeton.edu>
Mon, 16 Oct 2006 21:59:05 +0000 (21:59 +0000)
18 files changed:
PLC/Attributes.py [deleted file]
PLC/Methods/AddAttribute.py [deleted file]
PLC/Methods/AddSliceAttribute.py
PLC/Methods/AddSliceAttributeType.py [new file with mode: 0644]
PLC/Methods/DeleteAttribute.py [deleted file]
PLC/Methods/DeleteSliceAttributeType.py [new file with mode: 0644]
PLC/Methods/GetAttributes.py [deleted file]
PLC/Methods/GetSliceAttributeTypes.py [new file with mode: 0644]
PLC/Methods/GetSliceAttributes.py
PLC/Methods/UpdateAttribute.py [deleted file]
PLC/Methods/UpdateSliceAttributeType.py [new file with mode: 0644]
PLC/Methods/__init__.py
PLC/Roles.py
PLC/SliceAttributeTypes.py [new file with mode: 0644]
PLC/SliceAttributes.py
PLC/__init__.py
Test.py
planetlab4.sql

diff --git a/PLC/Attributes.py b/PLC/Attributes.py
deleted file mode 100644 (file)
index 77623d2..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-from types import StringTypes
-
-from PLC.Faults import *
-from PLC.Parameter import Parameter
-from PLC.Table import Row, Table
-from PLC.Roles import Role, Roles
-
-class Attribute(Row):
-    """
-    Representation of a row in the attributes table. To use, instantiate
-    with a dict of values.
-    """
-
-    table_name = 'attributes'
-    primary_key = 'attribute_id'
-    fields = {
-        'attribute_id': Parameter(int, "Attribute identifier"),
-        'name': Parameter(str, "Attribute name", max = 100),
-        'description': Parameter(str, "Attribute description", max = 254),
-        'min_role_id': Parameter(int, "Minimum (least powerful) role that can set or change this attribute"),
-        }
-
-    def __init__(self, api, fields = {}):
-        Row.__init__(self, fields)
-        self.api = api
-
-    def validate_name(self, name):
-        name = name.strip()
-
-        if not name:
-            raise PLCInvalidArgument, "Attribute name must be set"
-
-        conflicts = Attributes(self.api, [name])
-        for attribute_id, attribute in conflicts.iteritems():
-            if 'attribute_id' not in self or self['attribute_id'] != attribute_id:
-                raise PLCInvalidArgument, "Attribute name already in use"
-
-        return name
-
-    def validate_min_role_id(self, role_id):
-        roles = Roles(self.api)
-        if role_id not in roles:
-            raise PLCInvalidArgument, "Invalid role"
-
-        return role_id
-
-    def delete(self, commit = True):
-        """
-        Delete existing slice attribute type.
-        """
-
-        assert 'attribute_id' in self
-
-        # Clean up miscellaneous join tables
-        for table in ['attributes', 'slice_attribute']:
-            self.api.db.do("DELETE FROM %s" \
-                           " WHERE attribute_id = %d" % \
-                           (table, self['attribute_id']), self)
-
-        if commit:
-            self.api.db.commit()
-
-class Attributes(Table):
-    """
-    Representation of row(s) from the attributes table in the
-    database.
-    """
-
-    def __init__(self, api, attribute_id_or_name_list = None):
-       self.api = api
-
-        sql = "SELECT %s FROM attributes" % \
-              ", ".join(Attribute.fields)
-
-        if attribute_id_or_name_list:
-            # Separate the list into integers and strings
-            attribute_ids = filter(lambda attribute_id: isinstance(attribute_id, (int, long)),
-                                   attribute_id_or_name_list)
-            names = filter(lambda name: isinstance(name, StringTypes),
-                           attribute_id_or_name_list)
-            sql += " WHERE (False"
-            if attribute_ids:
-                sql += " OR attribute_id IN (%s)" % ", ".join(map(str, attribute_ids))
-            if names:
-                sql += " OR name IN (%s)" % ", ".join(api.db.quote(names))
-            sql += ")"
-
-        rows = self.api.db.selectall(sql)
-        for row in rows:
-            self[row['attribute_id']] = Attribute(api, row)
diff --git a/PLC/Methods/AddAttribute.py b/PLC/Methods/AddAttribute.py
deleted file mode 100644 (file)
index 34cb104..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-from PLC.Faults import *
-from PLC.Method import Method
-from PLC.Parameter import Parameter, Mixed
-from PLC.Attributes import Attribute, Attributes
-from PLC.Auth import PasswordAuth
-
-can_update = lambda (field, value): field in \
-             ['description', 'min_role_id']
-
-class AddAttribute(Method):
-    """
-    Adds a new type of attribute. Any fields specified in
-    attribute_fields are used, otherwise defaults are used.
-
-    Returns the new attribute_id (> 0) if successful, faults otherwise.
-    """
-
-    roles = ['admin']
-
-    update_fields = dict(filter(can_update, Attribute.fields.items()))
-
-    accepts = [
-        PasswordAuth(),
-        Attribute.fields['name'],
-        update_fields
-        ]
-
-    returns = Parameter(int, 'New attribute_id (> 0) if successful')
-
-    def call(self, auth, name, attribute_fields = {}):
-        attribute_fields = dict(filter(can_update, attribute_fields.items()))
-        attribute = Attribute(self.api, attribute_fields)
-        attribute['name'] = name
-        attribute.sync()
-
-        return attribute['attribute_id']
index b8d3a0c..e221be8 100644 (file)
@@ -1,7 +1,7 @@
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
-from PLC.Attributes import Attribute, Attributes
+from PLC.SliceAttributeTypes import SliceAttributeType, SliceAttributeTypes
 from PLC.Slices import Slice, Slices
 from PLC.Nodes import Node, Nodes
 from PLC.SliceAttributes import SliceAttribute, SliceAttributes
@@ -28,7 +28,7 @@ class AddSliceAttribute(Method):
         PasswordAuth(),
         Mixed(SliceAttribute.fields['slice_id'],
               SliceAttribute.fields['name']),
-        Mixed(SliceAttribute.fields['attribute_id'],
+        Mixed(SliceAttribute.fields['attribute_type_id'],
               SliceAttribute.fields['name']),
         SliceAttribute.fields['value'],
         Mixed(Node.fields['node_id'],
@@ -37,16 +37,16 @@ class AddSliceAttribute(Method):
 
     returns = Parameter(int, 'New slice_attribute_id (> 0) if successful')
 
-    def call(self, auth, slice_id_or_name, attribute_id_or_name, value, node_id_or_hostname = None):
+    def call(self, auth, slice_id_or_name, attribute_type_id_or_name, value, node_id_or_hostname = None):
         slices = Slices(self.api, [slice_id_or_name]).values()
         if not slices:
             raise PLCInvalidArgument, "No such slice"
         slice = slices[0]
 
-        attributes = Attributes(self.api, [attribute_id_or_name]).values()
-        if not attributes:
-            raise PLCInvalidArgument, "No such attribute"
-        attribute = attributes[0]
+        attribute_types = SliceAttributeTypes(self.api, [attribute_type_id_or_name]).values()
+        if not attribute_types:
+            raise PLCInvalidArgument, "No such slice attribute type"
+        attribute_type = attribute_types[0]
 
         if 'admin' not in self.caller['roles']:
             if self.caller['person_id'] in slice['person_ids']:
@@ -56,13 +56,13 @@ class AddSliceAttribute(Method):
             elif slice['site_id'] not in self.caller['site_ids']:
                 raise PLCPermissionDenied, "Specified slice not associated with any of your sites"
 
-            if attribute['min_role_id'] is not None and \
-               min(self.caller['role_ids']) > attribute['min_role_id']:
-                raise PLCPermissionDenied, "Not allowed to set the specified attribute"
+            if attribute_type['min_role_id'] is not None and \
+               min(self.caller['role_ids']) > attribute_type['min_role_id']:
+                raise PLCPermissionDenied, "Not allowed to set the specified slice attribute"
 
         slice_attribute = SliceAttribute(self.api)
         slice_attribute['slice_id'] = slice['slice_id']
-        slice_attribute['attribute_id'] = attribute['attribute_id']
+        slice_attribute['attribute_type_id'] = attribute_type['attribute_type_id']
         slice_attribute['value'] = value
 
         # Sliver attribute if node is specified
diff --git a/PLC/Methods/AddSliceAttributeType.py b/PLC/Methods/AddSliceAttributeType.py
new file mode 100644 (file)
index 0000000..413471e
--- /dev/null
@@ -0,0 +1,37 @@
+from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.SliceAttributeTypes import SliceAttributeType, SliceAttributeTypes
+from PLC.Auth import PasswordAuth
+
+can_update = lambda (field, value): field in \
+             ['description', 'min_role_id']
+
+class AddSliceAttributeType(Method):
+    """
+    Adds a new type of slice attribute. Any fields specified in
+    attribute_type_fields are used, otherwise defaults are used.
+
+    Returns the new attribute_type_id (> 0) if successful, faults
+    otherwise.
+    """
+
+    roles = ['admin']
+
+    update_fields = dict(filter(can_update, SliceAttributeType.fields.items()))
+
+    accepts = [
+        PasswordAuth(),
+        SliceAttributeType.fields['name'],
+        update_fields
+        ]
+
+    returns = Parameter(int, 'New attribute_id (> 0) if successful')
+
+    def call(self, auth, name, attribute_type_fields = {}):
+        attribute_type_fields = dict(filter(can_update, attribute_type_fields.items()))
+        attribute_type = SliceAttributeType(self.api, attribute_type_fields)
+        attribute_type['name'] = name
+        attribute_type.sync()
+
+        return attribute_type['attribute_type_id']
diff --git a/PLC/Methods/DeleteAttribute.py b/PLC/Methods/DeleteAttribute.py
deleted file mode 100644 (file)
index aafce7d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-from PLC.Faults import *
-from PLC.Method import Method
-from PLC.Parameter import Parameter, Mixed
-from PLC.Attributes import Attribute, Attributes
-from PLC.Auth import PasswordAuth
-
-class DeleteAttribute(Method):
-    """
-    Deletes the specified slice attribute.
-
-    Returns 1 if successful, faults otherwise.
-    """
-
-    roles = ['admin']
-
-    accepts = [
-        PasswordAuth(),
-        Mixed(Attribute.fields['attribute_id'],
-              Attribute.fields['name']),
-        ]
-
-    returns = Parameter(int, '1 if successful')
-
-    def call(self, auth, attribute_id_or_name):
-        attributes = Attributes(self.api, [attribute_id_or_name]).values()
-        if not attributes:
-            raise PLCInvalidArgument, "No such attribute"
-        attribute = attributes[0]
-
-        attribute.delete()
-
-        return 1
diff --git a/PLC/Methods/DeleteSliceAttributeType.py b/PLC/Methods/DeleteSliceAttributeType.py
new file mode 100644 (file)
index 0000000..45626f7
--- /dev/null
@@ -0,0 +1,32 @@
+from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.SliceAttributeTypes import SliceAttributeType, SliceAttributeTypes
+from PLC.Auth import PasswordAuth
+
+class DeleteSliceAttributeType(Method):
+    """
+    Deletes the specified slice attribute.
+
+    Returns 1 if successful, faults otherwise.
+    """
+
+    roles = ['admin']
+
+    accepts = [
+        PasswordAuth(),
+        Mixed(SliceAttributeType.fields['attribute_type_id'],
+              SliceAttributeType.fields['name']),
+        ]
+
+    returns = Parameter(int, '1 if successful')
+
+    def call(self, auth, attribute_type_id_or_name):
+        attribute_types = SliceAttributeTypes(self.api, [attribute_type_id_or_name]).values()
+        if not attribute_types:
+            raise PLCInvalidArgument, "No such slice attribute type"
+        attribute_type = attribute_types[0]
+
+        attribute_type.delete()
+
+        return 1
diff --git a/PLC/Methods/GetAttributes.py b/PLC/Methods/GetAttributes.py
deleted file mode 100644 (file)
index 8790e13..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-from PLC.Method import Method
-from PLC.Parameter import Parameter, Mixed
-from PLC.Auth import PasswordAuth
-from PLC.Attributes import Attribute, Attributes
-
-class GetAttributes(Method):
-    """
-    Return an array of structs containing details about all possible
-    slice and node attributes. If attribute_id_or_name_list is
-    specified, only the specified attributes will be queried.
-    """
-
-    roles = ['admin', 'pi', 'user', 'tech']
-
-    accepts = [
-        PasswordAuth(),
-        [Mixed(Attribute.fields['attribute_id'],
-               Attribute.fields['name'])],
-        ]
-
-    returns = [Attribute.fields]
-
-    def call(self, auth, attribute_id_or_name_list = None):
-        # Get slice attribute information
-        attributes = Attributes(self.api, attribute_id_or_name_list).values()
-       
-       # Turn each attribute into a real dict.
-       attributes = [dict(attribute) for attribute in attributes]
-
-        return attributes
diff --git a/PLC/Methods/GetSliceAttributeTypes.py b/PLC/Methods/GetSliceAttributeTypes.py
new file mode 100644 (file)
index 0000000..fa060b7
--- /dev/null
@@ -0,0 +1,30 @@
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.Auth import PasswordAuth
+from PLC.SliceAttributeTypes import SliceAttributeType, SliceAttributeTypes
+
+class GetSliceAttributeTypes(Method):
+    """
+    Return an array of structs containing details about all possible
+    slice and node attributes. If attribute_id_or_name_list is
+    specified, only the specified attributes will be queried.
+    """
+
+    roles = ['admin', 'pi', 'user', 'tech']
+
+    accepts = [
+        PasswordAuth(),
+        [Mixed(SliceAttributeType.fields['attribute_type_id'],
+               SliceAttributeType.fields['name'])],
+        ]
+
+    returns = [SliceAttributeType.fields]
+
+    def call(self, auth, attribute_type_id_or_name_list = None):
+        # Get slice attribute type information
+        attribute_types = SliceAttributeTypes(self.api, attribute_type_id_or_name_list).values()
+       
+       # Turn each attribute into a real dict.
+       attribute_types = [dict(attribute_type) for attribute_type in attribute_types]
+
+        return attribute_types
index 9d92c1e..be646c8 100644 (file)
@@ -2,6 +2,7 @@ from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.SliceAttributes import SliceAttribute, SliceAttributes
+from PLC.Sites import Site, Sites
 from PLC.Slices import Slice, Slices
 from PLC.Nodes import Node, Nodes
 from PLC.Auth import PasswordAuth
@@ -23,37 +24,26 @@ class GetSliceAttributes(Method):
 
     accepts = [
         PasswordAuth(),
-        Mixed(Slice.fields['slice_id'],
-              Slice.fields['name']),
         [SliceAttribute.fields['slice_attribute_id']],
         ]
 
     returns = [SliceAttribute.fields]
 
-    def call(self, auth, slice_id_or_name, slice_attribute_id_list = None):
-        slices = Slices(self.api, [slice_id_or_name]).values()
-        if not slices:
-            raise PLCInvalidArgument, "No such slice"
-        slice = slices[0]
-
+    def call(self, auth, slice_attribute_ids = None):
+       # If we are not admin, make sure to only return our own slice
+       # and sliver attributes.
         if 'admin' not in self.caller['roles']:
-            if self.caller['person_id'] in slice['person_ids']:
-                pass
-            elif 'pi' not in self.caller['roles']:
-                raise PLCPermissionDenied, "Not a member of the specified slice"
-            elif slice['site_id'] not in self.caller['site_ids']:
-                raise PLCPermissionDenied, "Specified slice not associated with any of your sites"
-
-        if slice_attribute_id_list is None:
-            slice_attribute_id_list = slice['slice_attribute_ids']
-        else:
-            if set(slice_attribute_id_list).intersection(slice['slice_attribute_ids']) != \
-               set(slice_attribute_id_list):
-                raise PLCInvalidArgument, "Invalid slice attribute ID(s)"
-
-        slice_attributes = SliceAttributes(self.api, slice_attribute_id_list).values()
-       # turn each slice attribute into a real dict
-       slice_attributes = [dict(slice_attribute) \
-                          for slice_attribute in slice_attributes]
+            if not slice_attribute_ids:
+                slice_attribute_ids = []
+                slices = Slices(self.api, self.caller['slice_ids']).values()
+                if 'pi' in self.caller['roles']:
+                    sites = Sites(self.api, self.caller['site_ids']).values()
+                    slices += Slices(self.api, sites['slice_ids']).values()
+                for slice in slices:
+                    slice_attribute_ids = set(slice_attribute_ids).union(slice['slice_attribute_ids'])
+
+        slice_attributes = SliceAttributes(self.api, slice_attribute_ids).values()
+
+       slice_attributes = [dict(slice_attribute) for slice_attribute in slice_attributes]
        
         return slice_attributes
diff --git a/PLC/Methods/UpdateAttribute.py b/PLC/Methods/UpdateAttribute.py
deleted file mode 100644 (file)
index 2ecfe45..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-from PLC.Faults import *
-from PLC.Method import Method
-from PLC.Parameter import Parameter, Mixed
-from PLC.Attributes import Attribute, Attributes
-from PLC.Auth import PasswordAuth
-
-can_update = lambda (field, value): field in \
-             ['description', 'min_role_id']
-
-class UpdateAttribute(Method):
-    """
-    Updates the parameters of an existing attribute with the values in
-    attribute_fields.
-
-    Returns 1 if successful, faults otherwise.
-    """
-
-    roles = ['admin']
-
-    update_fields = dict(filter(can_update, Attribute.fields.items()))
-
-    accepts = [
-        PasswordAuth(),
-        Mixed(Attribute.fields['attribute_id'],
-              Attribute.fields['name']),
-        update_fields
-        ]
-
-    returns = Parameter(int, '1 if successful')
-
-    def call(self, auth, attribute_id_or_name, attribute_fields):
-        attribute_fields = dict(filter(can_update, attribute_fields.items()))
-
-        attributes = Attributes(self.api, [attribute_id_or_name]).values()
-        if not attributes:
-            raise PLCInvalidArgument, "No such attribute"
-        attribute = attributes[0]
-
-        attribute.update(attribute_fields)
-
-        attribute.sync()
-
-        return 1
diff --git a/PLC/Methods/UpdateSliceAttributeType.py b/PLC/Methods/UpdateSliceAttributeType.py
new file mode 100644 (file)
index 0000000..3ab869c
--- /dev/null
@@ -0,0 +1,43 @@
+from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.SliceAttributeTypes import SliceAttributeType, SliceAttributeTypes
+from PLC.Auth import PasswordAuth
+
+can_update = lambda (field, value): field in \
+             ['description', 'min_role_id']
+
+class UpdateSliceAttributeType(Method):
+    """
+    Updates the parameters of an existing attribute with the values in
+    attribute_type_fields.
+
+    Returns 1 if successful, faults otherwise.
+    """
+
+    roles = ['admin']
+
+    update_fields = dict(filter(can_update, SliceAttributeType.fields.items()))
+
+    accepts = [
+        PasswordAuth(),
+        Mixed(SliceAttributeType.fields['attribute_type_id'],
+              SliceAttributeType.fields['name']),
+        update_fields
+        ]
+
+    returns = Parameter(int, '1 if successful')
+
+    def call(self, auth, attribute_type_id_or_name, attribute_type_fields):
+        attribute_type_fields = dict(filter(can_update, attribute_type_fields.items()))
+
+        attribute_types = SliceAttributeTypes(self.api, [attribute_type_id_or_name]).values()
+        if not attribute_types:
+            raise PLCInvalidArgument, "No such attribute"
+        attribute_type = attribute_types[0]
+
+        attribute_type.update(attribute_type_fields)
+
+        attribute_type.sync()
+
+        return 1
index 4ad102c..4511c72 100644 (file)
@@ -1 +1 @@
-methods = 'AddAddress AddAddressType AddAddressTypeToAddress AddAttribute AddBootState AddKey AddKeyType AddNetworkMethod AddNetworkType AddNodeGroup AddNodeNetwork AddNode AddNodeToNodeGroup AddNodeToPCU AddPCU AddPerson AddPersonToSite AddPersonToSlice AddRole AddRoleToPerson AddSite AddSliceAttribute AddSlice AddSliceToNodes AdmAddAddressType AdmAddNodeGroup AdmAddNodeNetwork AdmAddNode AdmAddNodeToNodeGroup AdmAddPerson AdmAddPersonToSite AdmAddSitePowerControlUnit AdmAddSite AdmAssociateNodeToPowerControlUnitPort AdmAuthCheck AdmDeleteAddressType AdmDeleteNodeGroup AdmDeleteNodeNetwork AdmDeleteNode AdmDeletePerson AdmDeleteSitePowerControlUnit AdmDeleteSite AdmDisassociatePowerControlUnitPort AdmGenerateNodeConfFile AdmGetAllAddressTypes AdmGetAllNodeNetworks AdmGetAllRoles AdmGetNodeGroupNodes AdmGetNodeGroups AdmGetNodes AdmGetPersonRoles AdmGetPersonSites AdmGetPersons AdmGetPowerControlUnitNodes AdmGetPowerControlUnits AdmGetSiteNodes AdmGetSitePersons AdmGetSitePowerControlUnits AdmGetSites AdmGrantRoleToPerson AdmIsPersonInRole AdmRebootNode AdmRemoveNodeFromNodeGroup AdmRemovePersonFromSite AdmRevokeRoleFromPerson AdmSetPersonEnabled AdmSetPersonPrimarySite AdmUpdateNodeGroup AdmUpdateNodeNetwork AdmUpdateNode AdmUpdatePerson AdmUpdateSitePowerControlUnit AdmUpdateSite AuthCheck BlacklistKey DeleteAddress DeleteAddressTypeFromAddress DeleteAddressType DeleteAttribute DeleteBootState DeleteKey DeleteKeyType DeleteNetworkMethod DeleteNetworkType DeleteNodeFromNodeGroup DeleteNodeFromPCU DeleteNodeGroup DeleteNodeNetwork DeleteNode DeletePCU DeletePersonFromSite DeletePersonFromSlice DeletePerson DeleteRoleFromPerson DeleteRole DeleteSite DeleteSliceAttribute DeleteSliceFromNodes DeleteSlice GetAddresses GetAddressTypes GetAttributes GetBootStates GetKeys GetKeyTypes GetNetworkMethods GetNetworkTypes GetNodeGroups GetNodeNetworks GetNodes GetPCUs GetPersons GetRoles GetSites GetSliceAttributes GetSlices RebootNode SetPersonPrimarySite UpdateAddress UpdateAddressType UpdateAttribute UpdateKey UpdateNodeGroup UpdateNodeNetwork UpdateNode UpdatePCU UpdatePerson UpdateSite UpdateSliceAttribute UpdateSlice  system.listMethods  system.methodHelp  system.methodSignature  system.multicall'.split()
+methods = 'AddAddressType AddAddressTypeToAddress AddBootState AddKey AddKeyType AddNetworkMethod AddNetworkType AddNodeGroup AddNodeNetwork AddNode AddNodeToNodeGroup AddNodeToPCU AddPCU AddPerson AddPersonToSite AddPersonToSlice AddRole AddRoleToPerson AddSiteAddress AddSite AddSliceAttribute AddSliceAttributeType AddSlice AddSliceToNodes AdmAddAddressType AdmAddNodeGroup AdmAddNodeNetwork AdmAddNode AdmAddNodeToNodeGroup AdmAddPerson AdmAddPersonToSite AdmAddSitePowerControlUnit AdmAddSite AdmAssociateNodeToPowerControlUnitPort AdmAuthCheck AdmDeleteAddressType AdmDeleteNodeGroup AdmDeleteNodeNetwork AdmDeleteNode AdmDeletePerson AdmDeleteSitePowerControlUnit AdmDeleteSite AdmDisassociatePowerControlUnitPort AdmGenerateNodeConfFile AdmGetAllAddressTypes AdmGetAllNodeNetworks AdmGetAllRoles AdmGetNodeGroupNodes AdmGetNodeGroups AdmGetNodes AdmGetPersonRoles AdmGetPersonSites AdmGetPersons AdmGetPowerControlUnitNodes AdmGetPowerControlUnits AdmGetSiteNodes AdmGetSitePersons AdmGetSitePowerControlUnits AdmGetSites AdmGrantRoleToPerson AdmIsPersonInRole AdmRebootNode AdmRemoveNodeFromNodeGroup AdmRemovePersonFromSite AdmRevokeRoleFromPerson AdmSetPersonEnabled AdmSetPersonPrimarySite AdmUpdateNodeGroup AdmUpdateNodeNetwork AdmUpdateNode AdmUpdatePerson AdmUpdateSitePowerControlUnit AdmUpdateSite AuthCheck BlacklistKey DeleteAddress DeleteAddressTypeFromAddress DeleteAddressType DeleteBootState DeleteKey DeleteKeyType DeleteNetworkMethod DeleteNetworkType DeleteNodeFromNodeGroup DeleteNodeFromPCU DeleteNodeGroup DeleteNodeNetwork DeleteNode DeletePCU DeletePersonFromSite DeletePersonFromSlice DeletePerson DeleteRoleFromPerson DeleteRole DeleteSite DeleteSliceAttribute DeleteSliceAttributeType DeleteSliceFromNodes DeleteSlice GetAddresses GetAddressTypes GetBootStates GetKeys GetKeyTypes GetNetworkMethods GetNetworkTypes GetNodeGroups GetNodeNetworks GetNodes GetPCUs GetPersons GetRoles GetSites GetSliceAttributes GetSliceAttributeTypes GetSlices RebootNode SetPersonPrimarySite UpdateAddress UpdateAddressType UpdateKey UpdateNodeGroup UpdateNodeNetwork UpdateNode UpdatePCU UpdatePerson UpdateSite UpdateSliceAttribute UpdateSliceAttributeType UpdateSlice  system.listMethods  system.methodHelp  system.methodSignature  system.multicall'.split()
index 40c3277..8896647 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: Roles.py,v 1.2 2006/10/06 18:19:41 mlhuang Exp $
+# $Id: Roles.py,v 1.3 2006/10/10 21:54:59 mlhuang Exp $
 #
 
 from types import StringTypes
@@ -61,7 +61,7 @@ class Role(Row):
                            " WHERE role_id = %d" % \
                            (table, self['role_id']), self)
 
-        self.api.db.do("DELETE FROM attributes WHERE min_role_id = %d" % \
+        self.api.db.do("DELETE FROM slice_attribute_types WHERE min_role_id = %d" % \
                        self['role_id'])
 
         if commit:
diff --git a/PLC/SliceAttributeTypes.py b/PLC/SliceAttributeTypes.py
new file mode 100644 (file)
index 0000000..e719868
--- /dev/null
@@ -0,0 +1,91 @@
+from types import StringTypes
+
+from PLC.Faults import *
+from PLC.Parameter import Parameter
+from PLC.Table import Row, Table
+from PLC.Roles import Role, Roles
+
+class SliceAttributeType(Row):
+    """
+    Representation of a row in the slice_attribute_types table. To
+    use, instantiate with a dict of values.
+    """
+
+    table_name = 'slice_attribute_types'
+    primary_key = 'attribute_type_id'
+    fields = {
+        'attribute_type_id': Parameter(int, "Slice attribute type identifier"),
+        'name': Parameter(str, "Slice attribute type name", max = 100),
+        'description': Parameter(str, "Slice attribute type description", max = 254),
+        'min_role_id': Parameter(int, "Minimum (least powerful) role that can set or change this attribute"),
+        }
+
+    def __init__(self, api, fields = {}):
+        Row.__init__(self, fields)
+        self.api = api
+
+    def validate_name(self, name):
+        name = name.strip()
+
+        if not name:
+            raise PLCInvalidArgument, "Slice attribute type name must be set"
+
+        conflicts = SliceAttributeTypes(self.api, [name])
+        for attribute_type_id, attribute in conflicts.iteritems():
+            if 'attribute_type_id' not in self or self['attribute_type_id'] != attribute_type_id:
+                raise PLCInvalidArgument, "Slice attribute type name already in use"
+
+        return name
+
+    def validate_min_role_id(self, role_id):
+        roles = Roles(self.api)
+        if role_id not in roles:
+            raise PLCInvalidArgument, "Invalid role"
+
+        return role_id
+
+    def delete(self, commit = True):
+        """
+        Delete existing slice attribute type.
+        """
+
+        assert 'attribute_type_id' in self
+
+        # Clean up miscellaneous join tables
+        for table in ['slice_attribute_types', 'slice_attribute']:
+            self.api.db.do("DELETE FROM %s" \
+                           " WHERE attribute_type_id = %d" % \
+                           (table, self['attribute_type_id']), self)
+
+        if commit:
+            self.api.db.commit()
+
+class SliceAttributeTypes(Table):
+    """
+    Representation of row(s) from the slice_attribute_types table in the
+    database.
+    """
+
+    def __init__(self, api, attribute_type_id_or_name_list = None):
+       self.api = api
+
+        sql = "SELECT %s FROM slice_attribute_types" % \
+              ", ".join(SliceAttributeType.fields)
+
+        if attribute_type_id_or_name_list:
+            # Separate the list into integers and strings
+            attribute_type_ids = filter(lambda attribute_type_id: isinstance(attribute_type_id, (int, long)),
+                                   attribute_type_id_or_name_list)
+            names = filter(lambda name: isinstance(name, StringTypes),
+                           attribute_type_id_or_name_list)
+            sql += " WHERE (False"
+            if attribute_type_ids:
+                sql += " OR attribute_type_id IN (%s)" % ", ".join(map(str, attribute_type_ids))
+            if names:
+                sql += " OR name IN (%s)" % ", ".join(api.db.quote(names))
+            sql += ")"
+
+        rows = self.api.db.selectall(sql)
+        for row in rows:
+            self[row['attribute_type_id']] = SliceAttributeType(api, row)
index bf51c29..dd91131 100644 (file)
@@ -3,7 +3,7 @@ from types import StringTypes
 from PLC.Faults import *
 from PLC.Parameter import Parameter
 from PLC.Table import Row, Table
-from PLC.Attributes import Attribute, Attributes
+from PLC.SliceAttributeTypes import SliceAttributeType, SliceAttributeTypes
 
 class SliceAttribute(Row):
     """
@@ -17,10 +17,10 @@ class SliceAttribute(Row):
         'slice_attribute_id': Parameter(int, "Slice attribute identifier"),
         'slice_id': Parameter(int, "Slice identifier"),
         'node_id': Parameter(int, "Node identifier, if a sliver attribute"),
-        'attribute_id': Attribute.fields['attribute_id'],
-        'name': Attribute.fields['name'],
-        'description': Attribute.fields['description'],
-        'min_role_id': Attribute.fields['min_role_id'],
+        'attribute_type_id': SliceAttributeType.fields['attribute_type_id'],
+        'name': SliceAttributeType.fields['name'],
+        'description': SliceAttributeType.fields['description'],
+        'min_role_id': SliceAttributeType.fields['min_role_id'],
         # XXX Arbitrary max, make configurable
         'value': Parameter(str, "Slice attribute value", max = 254),
         }
@@ -57,7 +57,8 @@ class SliceAttributes(dict):
         sql = "SELECT %s FROM view_slice_attributes" % \
               ", ".join(SliceAttribute.fields)
 
-        sql += " WHERE slice_attribute_id IN (%s)" % ", ".join(map(str, slice_attribute_id_list))
+        if slice_attribute_id_list:
+            sql += " WHERE slice_attribute_id IN (%s)" % ", ".join(map(str, slice_attribute_id_list))
 
         rows = self.api.db.selectall(sql)
  
index ea834ec..704a114 100644 (file)
@@ -1 +1 @@
-all = 'Addresses AddressTypes API Attributes Auth BootStates Config Debug Faults Keys KeyTypes Method NetworkMethods NetworkTypes NodeGroups NodeNetworks Nodes Parameter PCUs Persons POD PostgreSQL Roles Sites SliceAttributes SliceInstantiations Slices Table'.split()
+all = 'Addresses AddressTypes API Auth BootStates Config Debug Faults Keys KeyTypes Method NetworkMethods NetworkTypes NodeGroups NodeNetworks Nodes Parameter PCUs Persons POD PostgreSQL Roles Sites SliceAttributes SliceAttributeTypes SliceInstantiations Slices Table'.split()
diff --git a/Test.py b/Test.py
index e845d11..35ad886 100755 (executable)
--- a/Test.py
+++ b/Test.py
@@ -5,7 +5,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: Test.py,v 1.8 2006/10/03 19:33:16 mlhuang Exp $
+# $Id: Test.py,v 1.9 2006/10/11 15:46:09 mlhuang Exp $
 #
 
 from pprint import pprint
@@ -341,10 +341,6 @@ for nodegroup_id in nodegroup_ids:
     assert set(nodegroup_node_ids) == set(node_ids)
     print "=>", nodegroup_node_ids
 
-print "AdmGetAllNodeNetworkBandwidthLimits",
-bwlimits = AdmGetAllNodeNetworkBandwidthLimits(admin)
-print "=>", bwlimits
-
 # Add node networks
 nodenetwork_ids = []
 for node_id in node_ids:
@@ -410,41 +406,41 @@ for node_id in node_ids:
                 assert address == locals()[key]
     print "=>", [nodenetwork['nodenetwork_id'] for nodenetwork in nodenetworks]
 
-# Add attribute types
-attribute_ids = []
+# Add node attribute types
+attribute_type_ids = []
 for i in range(3):
     name = randstr(100)
     description = randstr(254)
     min_role_id = random.sample(roles.values(), 1)[0]
 
-    # Add attribute
-    print "AddAttribute",
-    attribute_id = AddAttribute(admin, name,
-                                {'description': description,
-                                 'min_role_id': min_role_id})
+    # Add slice attribute type
+    print "AddSliceAttributeType",
+    attribute_type_id = AddSliceAttributeType(admin, name,
+                                         {'description': description,
+                                          'min_role_id': min_role_id})
 
-    # Should return a unique attribute_id
-    assert attribute_id not in attribute_ids
-    attribute_ids.append(attribute_id)
-    print "=>", attribute_id
+    # Should return a unique attribute_type_id
+    assert attribute_type_id not in attribute_type_ids
+    attribute_type_ids.append(attribute_type_id)
+    print "=>", attribute_type_id
 
-    # Check attribute
-    print "GetAttributes(%d)" % attribute_id,
-    attribute = GetAttributes(admin, [attribute_id])[0]
+    # Check slice attribute type
+    print "GetSliceAttributeTypes(%d)" % attribute_type_id,
+    attribute_type = GetSliceAttributeTypes(admin, [attribute_type_id])[0]
     for key in 'min_role_id', 'description':
-        assert unicmp(attribute[key], locals()[key])
+        assert unicmp(attribute_type[key], locals()[key])
     print "=> OK"
 
-    # Update attribute
+    # Update slice attribute type
     description = randstr(254)
     min_role_id = random.sample(roles.values(), 1)[0]
-    print "UpdateAttribute(%d)" % attribute_id,
-    UpdateAttribute(admin, attribute_id,
-                    {'description': description,
-                     'min_role_id': min_role_id})
-    attribute = GetAttributes(admin, [attribute_id])[0]
+    print "UpdateSliceAttributeType(%d)" % attribute_type_id,
+    UpdateSliceAttributeType(admin, attribute_type_id,
+                             {'description': description,
+                              'min_role_id': min_role_id})
+    attribute_type = GetSliceAttributeTypes(admin, [attribute_type_id])[0]
     for key in 'min_role_id', 'description':
-        assert unicmp(attribute[key], locals()[key])
+        assert unicmp(attribute_type[key], locals()[key])
     print "=> OK"
 
 # Add slices and slice attributes
@@ -488,18 +484,18 @@ for site in sites:
         # XXX Add people to slice
         
         # Set slice/sliver attributes
-        for attribute_id in attribute_ids:
+        for attribute_type_id in attribute_type_ids:
             value = randstr(254)
             # Make it a sliver attribute with 50% probability
             # node_id = random.sample(node_ids + [None] * len(node_ids), 1)[0]
             node_id = None
 
             # Add slice attribute
-            print "AddSliceAttribute(%s, %d)" % (name, attribute_id),
+            print "AddSliceAttribute(%s, %d)" % (name, attribute_type_id),
             if node_id is None:
-                slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_id, value)
+                slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_type_id, value)
             else:
-                slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_id, value, node_id)
+                slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_type_id, value, node_id)
 
             # Should return a unique slice_attribute_id
             assert slice_attribute_id not in slice_attribute_ids
@@ -508,8 +504,8 @@ for site in sites:
 
             # Check slice attribute
             print "GetSliceAttributes(%d)" % slice_attribute_id,
-            slice_attribute = GetSliceAttributes(admin, slice_id, [slice_attribute_id])[0]
-            for key in 'attribute_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
+            slice_attribute = GetSliceAttributes(admin, [slice_attribute_id])[0]
+            for key in 'attribute_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
                 assert unicmp(slice_attribute[key], locals()[key])
             print "=> OK"
 
@@ -518,8 +514,8 @@ for site in sites:
             description = randstr(2048)
             print "UpdateSliceAttribute(%s)" % name,
             UpdateSliceAttribute(admin, slice_attribute_id, value)
-            slice_attribute = GetSliceAttributes(admin, slice_id, [slice_attribute_id])[0]
-            for key in 'attribute_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
+            slice_attribute = GetSliceAttributes(admin, [slice_attribute_id])[0]
+            for key in 'attribute_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
                 assert unicmp(slice_attribute[key], locals()[key])
             print "=> OK"
 
@@ -548,20 +544,20 @@ print "GetSlices",
 assert not GetSlices(admin, slice_ids)
 print "=> []"
 
-# Delete attributes
-for attribute_id in attribute_ids:
+# Delete slice attribute types
+for attribute_type_id in attribute_type_ids:
     # Delete attribute
-    print "DeleteAttribute(%d)" % attribute_id,
-    DeleteAttribute(admin, attribute_id)
-    assert not GetAttributes(admin, [attribute_id])
+    print "DeleteAttribute(%d)" % attribute_type_id,
+    DeleteSliceAttributeType(admin, attribute_type_id)
+    assert not GetSliceAttributeTypes(admin, [attribute_type_id])
 
     # Make sure it really deleted it
-    attributes = GetAttributes(admin, attribute_ids)
-    assert attribute_id not in [attribute['attribute_id'] for attribute in attributes]
+    attribute_types = GetSliceAttributeTypes(admin, attribute_type_ids)
+    assert attribute_type_id not in [attribute_type['attribute_type_id'] for attribute_type in attribute_types]
     print "=> OK"
 
 print "GetAttributes",
-assert not GetAttributes(admin, attribute_ids)
+assert not GetSliceAttributeTypes(admin, attribute_type_ids)
 print "=> []"
 
 # Delete node networks
index c4cbe4b..9fefda0 100644 (file)
@@ -9,7 +9,7 @@
 --
 -- Copyright (C) 2006 The Trustees of Princeton University
 --
--- $Id: planetlab4.sql,v 1.10 2006/10/11 20:49:39 mlhuang Exp $
+-- $Id: planetlab4.sql,v 1.11 2006/10/13 15:07:24 tmack Exp $
 --
 
 --------------------------------------------------------------------------------
@@ -506,8 +506,8 @@ GROUP BY person_id;
 --------------------------------------------------------------------------------
 
 -- Slice attribute types
-CREATE TABLE attributes (
-    attribute_id serial PRIMARY KEY, -- Attribute type identifier
+CREATE TABLE slice_attribute_types (
+    attribute_type_id serial PRIMARY KEY, -- Attribute type identifier
     name text UNIQUE NOT NULL, -- Attribute name
     description text, -- Attribute description
     min_role_id integer REFERENCES roles DEFAULT 10 -- If set, minimum (least powerful) role that can set or change this attribute
@@ -518,7 +518,7 @@ CREATE TABLE slice_attribute (
     slice_attribute_id serial PRIMARY KEY, -- Slice attribute identifier
     slice_id integer REFERENCES slices NOT NULL, -- Slice identifier
     node_id integer REFERENCES nodes, -- Sliver attribute if set
-    attribute_id integer REFERENCES attributes NOT NULL, -- Attribute type identifier
+    attribute_type_id integer REFERENCES slice_attribute_types NOT NULL, -- Attribute type identifier
     value text
 ) WITH OIDS;
 CREATE INDEX slice_attribute_slice_id_idx ON slice_attribute (slice_id);
@@ -745,13 +745,13 @@ SELECT
 slice_attribute.slice_attribute_id,
 slice_attribute.slice_id,
 slice_attribute.node_id,
-attributes.attribute_id,
-attributes.name,
-attributes.description,
-attributes.min_role_id,
+slice_attribute_types.attribute_type_id,
+slice_attribute_types.name,
+slice_attribute_types.description,
+slice_attribute_types.min_role_id,
 slice_attribute.value
 FROM slice_attribute
-INNER JOIN attributes USING (attribute_id);
+INNER JOIN slice_attribute_types USING (attribute_type_id);
 
 --------------------------------------------------------------------------------
 -- Built-in maintenance account and default site