implemented Interfaces, InterfaceTags, Messages, NetworkMethods, NetworkTypes, NodeGroups
authorTony Mack <tmack@paris.CS.Princeton.EDU>
Mon, 1 Oct 2012 20:45:59 +0000 (16:45 -0400)
committerTony Mack <tmack@paris.CS.Princeton.EDU>
Mon, 1 Oct 2012 20:45:59 +0000 (16:45 -0400)
PLC/InterfaceTags.py
PLC/Interfaces.py
PLC/Messages.py
PLC/NetworkMethods.py
PLC/NetworkTypes.py
PLC/NodeGroups.py

index af1deb4..4ed6e96 100644 (file)
@@ -4,20 +4,19 @@
 from PLC.Faults import *
 from PLC.Parameter import Parameter
 from PLC.Filter import Filter
-from PLC.Table import Row, Table
+from PLC.Storage.AlchemyObject import AlchemyObj
 from PLC.TagTypes import TagType, TagTypes
 from PLC.Interfaces import Interface
 
-class InterfaceTag(Row):
+class InterfaceTag(AlchemyObj):
     """
     Representation of a row in the interface_tag.
     To use, instantiate with a dict of values.
     """
 
-    table_name = 'interface_tag'
-    primary_key = 'interface_tag_id'
+    table_name = 'interface_tags'
     fields = {
-        'interface_tag_id': Parameter(int, "Interface setting identifier"),
+        'interface_tag_id': Parameter(int, "Interface setting identifier", primary_key=True),
         'interface_id': Interface.fields['interface_id'],
         'ip': Interface.fields['ip'],
         'tag_type_id': TagType.fields['tag_type_id'],
@@ -29,26 +28,37 @@ class InterfaceTag(Row):
 
         }
 
-class InterfaceTags(Table):
+    def sync(self, commit = True, validate=True):
+        AlchemyObj.sync(self, commit, validate)
+        if 'interface_tag_id' not in self:
+            # Before a new slice is added, delete expired slices
+            #expired = Slices(self.api, expires = -int(time.time()))
+            #for slice in expired:
+            #    slice.delete(commit)
+            AlchemyObj.insert(self, dict(self))
+        else:
+            AlchemyObj.update(self, {'interface_tag_id': self['interface_tag_id']}, dict(self))
+
+    def delete(self, commit=True):
+        assert 'interface_tag_id' in self
+        AlchemyObj.delete(self, dict(self))        
+
+
+class InterfaceTags(list):
     """
     Representation of row(s) from the interface_tag table in the
     database.
     """
 
     def __init__(self, api, interface_tag_filter = None, columns = None):
-        Table.__init__(self, api, InterfaceTag, columns)
-
-        sql = "SELECT %s FROM view_interface_tags WHERE True" % \
-              ", ".join(self.columns)
-
-        if interface_tag_filter is not None:
-            if isinstance(interface_tag_filter, (list, tuple, set, int, long)):
-                interface_tag_filter = Filter(InterfaceTag.fields, {'interface_tag_id': interface_tag_filter})
-            elif isinstance(interface_tag_filter, dict):
-                interface_tag_filter = Filter(InterfaceTag.fields, interface_tag_filter)
-            else:
-                raise PLCInvalidArgument, "Wrong interface setting filter %r"%interface_tag_filter
-            sql += " AND (%s) %s" % interface_tag_filter.sql(api)
-
+        if not interface_tag_filter:
+            interface_tags = InterfaceTag().select()
+        if isinstance(interface_tag_filter, (list, tuple, set, int, long)):
+            interface_tags = InterfaceTag().select(filter={'interface_tag_id': interface_tag_filter})
+        elif isinstance(interface_tag_filter, dict):
+            interface_tags = InterfaceTag().select(filter=interface_tag_filter})
+        else:
+            raise PLCInvalidArgument, "Wrong interface setting filter %r"%interface_tag_filter
 
-        self.selectall(sql)
+        for interface_tag in interface_tags:
+            self.append(interface_tag)
index 0e6c728..6de99fe 100644 (file)
@@ -11,9 +11,8 @@ import struct
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
-from PLC.Filter import Filter
 from PLC.Debug import profile
-from PLC.Table import Row, Table
+from PLC.Storage.AlchemyObject import AlchemyObj
 from PLC.NetworkTypes import NetworkType, NetworkTypes
 from PLC.NetworkMethods import NetworkMethod, NetworkMethods
 import PLC.Nodes
@@ -61,18 +60,17 @@ def in_same_network(address1, address2, netmask):
     return in_same_network_ipv4(address1, address2, netmask) or \
            in_same_network_ipv6(address1, address2, netmask) 
 
-class Interface(Row):
+class Interface(AlchemyObj):
     """
     Representation of a row in the interfaces table. To use, optionally
     instantiate with a dict of values. Update as you would a
     dict. Commit to the database with sync().
     """
 
-    table_name = 'interfaces'
-    primary_key = 'interface_id'
+    tablename = 'interfaces'
     join_tables = ['interface_tag']
     fields = {
-        'interface_id': Parameter(int, "Node interface identifier"),
+        'interface_id': Parameter(int, "Node interface identifier", primary_key=True),
         'method': Parameter(str, "Addressing method (e.g., 'static' or 'dhcp')"),
         'type': Parameter(str, "Address type (e.g., 'ipv4')"),
         'ip': Parameter(str, "IP address", nullok = True),
@@ -87,11 +85,10 @@ class Interface(Row):
         'hostname': Parameter(str, "(Optional) Hostname", nullok = True),
         'node_id': Parameter(int, "Node associated with this interface"),
         'is_primary': Parameter(bool, "Is the primary interface for this node"),
-        'interface_tag_ids' : Parameter([int], "List of interface settings"),
+        'interface_tag_ids' : Parameter([int], "List of interface settings", joined=True),
         'last_updated': Parameter(int, "Date and time when node entry was created", ro = True),
         }
 
-    view_tags_name = "view_interface_tags"
     tags = {}
 
     def validate_method(self, method):
@@ -190,7 +187,7 @@ class Interface(Row):
         """
 
         # Basic validation
-        Row.validate(self)
+        AlchemyObj.validate(self)
 
         assert 'method' in self
         method = self['method']
@@ -244,60 +241,46 @@ class Interface(Row):
         Update col_name field with current time
         """
 
-        assert 'interface_id' in self
-        assert self.table_name
-
-        self.api.db.do("UPDATE %s SET %s = CURRENT_TIMESTAMP " % (self.table_name, col_name) + \
-                       " where interface_id = %d" % (self['interface_id']) )
-        self.sync(commit)
+        pass
 
     def update_last_updated(self, commit = True):
         self.update_timestamp('last_updated', commit)
 
+    def sync(self, commit=True, validate=True):
+        AlchemyObj.sync(self, commit, validate)
+        if 'interface_id' not in self:
+            AlchemyObj.insert(self, dict(self))
+        else:
+            AlchemyObj.update(self, {'interface_id': self['interface_id']}, dict(self))
+
     def delete(self,commit=True):
         ### need to cleanup ilinks
-        self.api.db.do("DELETE FROM ilink WHERE src_interface_id=%d OR dst_interface_id=%d" % \
-                           (self['interface_id'],self['interface_id']))
-        
-        Row.delete(self)
+        AlchemyObj.delete(self, dict(self)
 
-class Interfaces(Table):
+
+class Interfaces(list):
     """
     Representation of row(s) from the interfaces table in the
     database.
     """
 
     def __init__(self, api, interface_filter = None, columns = None):
-        Table.__init__(self, api, Interface, columns)
-
         # the view that we're selecting upon: start with view_nodes
-        view = "view_interfaces"
-        # as many left joins as requested tags
-        for tagname in self.tag_columns:
-            view= "%s left join %s using (%s)"%(view,Interface.tagvalue_view_name(tagname),
-                                                Interface.primary_key)
-
-        sql = "SELECT %s FROM %s WHERE True" % \
-            (", ".join(self.columns.keys()+self.tag_columns.keys()),view)
-
-        if interface_filter is not None:
-            if isinstance(interface_filter, (list, tuple, set)):
-                # Separate the list into integers and strings
-                ints = filter(lambda x: isinstance(x, (int, long)), interface_filter)
-                strs = filter(lambda x: isinstance(x, StringTypes), interface_filter)
-                interface_filter = Filter(Interface.fields, {'interface_id': ints, 'ip': strs})
-                sql += " AND (%s) %s" % interface_filter.sql(api, "OR")
-            elif isinstance(interface_filter, dict):
-                allowed_fields=dict(Interface.fields.items()+Interface.tags.items())
-                interface_filter = Filter(allowed_fields, interface_filter)
-                sql += " AND (%s) %s" % interface_filter.sql(api)
-            elif isinstance(interface_filter, int):
-                interface_filter = Filter(Interface.fields, {'interface_id': [interface_filter]})
-                sql += " AND (%s) %s" % interface_filter.sql(api)
-            elif isinstance (interface_filter, StringTypes):
-                interface_filter = Filter(Interface.fields, {'ip':[interface_filter]})
-                sql += " AND (%s) %s" % interface_filter.sql(api, "AND")
-            else:
-                raise PLCInvalidArgument, "Wrong interface filter %r"%interface_filter
-
-        self.selectall(sql)
+        if not interface_filter:
+            interfaces = Interface().select()
+        elif isinstance(interface_filter, (list, tuple, set)):
+            # Separate the list into integers and strings
+            ints = filter(lambda x: isinstance(x, (int, long)), interface_filter)
+            strs = filter(lambda x: isinstance(x, StringTypes), interface_filter)
+            interfaces = Interface().select(filter={'interface_id': ints, 'ip': strs})
+        elif isinstance(interface_filter, dict):
+            interfaces = Interface().select(filter=interface_filter})
+        elif isinstance(interface_filter, int):
+            interfaces = Interface().select(filter={'interface_id': interface_filter})
+        elif isinstance (interface_filter, StringTypes):
+            interfaces = Interface().select(filter={'ip': interface_filter})
+        else:
+            raise PLCInvalidArgument, "Wrong interface filter %r"%interface_filter
+
+        for interface in interfaces:
+            self.append(interface)
index 3696926..09f9335 100644 (file)
@@ -8,43 +8,49 @@
 from PLC.Parameter import Parameter
 from PLC.Table import Row, Table
 from PLC.Filter import Filter
+from PLC.Storage.AlchemyObject import AlchemyObj
 
-class Message(Row):
+class Message(AlchemyObj):
     """
     Representation of a row in the messages table.
     """
 
-    table_name = 'messages'
-    primary_key = 'message_id'
+    tablename = 'messages'
     fields = {
-        'message_id': Parameter(str, "Message identifier"),
+        'message_id': Parameter(str, "Message identifier", primary_key=True),
         'subject': Parameter(str, "Message summary", nullok = True),
         'template': Parameter(str, "Message template", nullok = True),
         'enabled': Parameter(bool, "Message is enabled"),
         }
 
-class Messages(Table):
+    def sync(self, commit=True, validate=True):
+        AlchemyObj.sync(self, commit, validate)
+        if 'message_id' not in self:
+            # Before a new slice is added, delete expired slices
+            #expired = Slices(self.api, expires = -int(time.time()))
+            #for slice in expired:
+            #    slice.delete(commit)
+            AlchemyObj.insert(self, dict(self))
+        else:
+            AlchemyObj.update(self, {'message_id': self['message_id']}, dict(self))
+
+    def delete(self, commit = True):
+        AlchemyObj.delete(self, dict(self))
+
+class Messages(list):
     """
     Representation of row(s) from the messages table in the database.
     """
 
     def __init__(self, api, message_filter = None, columns = None, enabled = None):
-        Table.__init__(self, api, Message, columns)
-
-        sql = "SELECT %s from messages WHERE True" % \
-              ", ".join(self.columns)
-
-        if enabled is not None:
-            sql += " AND enabled IS %s" % enabled
-
-        if message_filter is not None:
-            if isinstance(message_filter, (list, tuple, set, int, long)):
-                message_filter = Filter(Message.fields, {'message_id': message_filter})
-                sql += " AND (%s) %s" % message_filter.sql(api, "OR")
-            elif isinstance(message_filter, dict):
-                message_filter = Filter(Message.fields, message_filter)
-                sql += " AND (%s) %s" % message_filter.sql(api, "AND")
-            else:
-                raise PLCInvalidArgument, "Wrong message filter %r"%message_filter
-
-        self.selectall(sql)
+        if not message_filter:
+            messages = Message().select()
+        if isinstance(message_filter, (list, tuple, set, int, long)):
+            messages = Message().select(filter={'message_id': message_filter})
+        elif isinstance(message_filter, dict):
+            messages = Message().select(filter=message_filter)
+        else:
+            raise PLCInvalidArgument, "Wrong message filter %r"%message_filter
+    
+        for message in messages:
+            self.append(message)
index a54934d..97e2505 100644 (file)
@@ -1,25 +1,22 @@
 #
 # Functions for interacting with the network_methods table in the database
 #
-# Mark Huang <mlhuang@cs.princeton.edu>
-# Copyright (C) 2006 The Trustees of Princeton University
 #
-
+from types import StringTypes
 from PLC.Faults import *
 from PLC.Parameter import Parameter
-from PLC.Table import Row, Table
+from PLC.Storage.AlchemyObject import AlchemyObj
 
-class NetworkMethod(Row):
+class NetworkMethod(AlchemyObj):
     """
     Representation of a row in the network_methods table. To use,
     instantiate with a dict of values.
     """
 
-    table_name = 'network_methods'
-    primary_key = 'method'
+    tablename = 'network_methods'
     join_tables = ['interfaces']
     fields = {
-        'method': Parameter(str, "Network method", max = 20),
+        'method': Parameter(str, "Network method", max = 20, primary_key=True),
         }
 
     def validate_method(self, name):
@@ -28,24 +25,34 @@ class NetworkMethod(Row):
             raise PLCInvalidArgument, "Network method must be specified"
 
         # Make sure network method does not alredy exist
-        conflicts = NetworkMethods(self.api, [name])
+        conflicts = NetworkMethods(self.api, name)
         if conflicts:
             raise PLCInvalidArgument, "Network method name already in use"
 
         return name
 
-class NetworkMethods(Table):
+    def sync(self, commit = True, validate=True):
+        AlchemyObj.sync(self, commit, validate)
+        AlchemyObj.insert(self, dict(self))
+
+    def delete(self, commit=True):
+        assert method in self
+        AlchemyObj.delete(self, dict(self))
+        
+
+class NetworkMethods(list):
     """
     Representation of the network_methods table in the database.
     """
 
     def __init__(self, api, methods = None):
-        Table.__init__(self, api, NetworkMethod)
-
-        sql = "SELECT %s FROM network_methods" % \
-              ", ".join(NetworkMethod.fields)
 
-        if methods:
-            sql += " WHERE method IN (%s)" % ", ".join( [ api.db.quote (m) for m in methods ] )
+        if not methods:
+            network_methods = NetworkMethod().select()
+        elif isinstance(methods, StringTypes):
+            network_methods = NetworkMethod().select(filter={'method': methods})
+        else:
+            raise PLCInvalidArgument, "Wrong network method filter %r"%methods
 
-        self.selectall(sql)
+        self.extend(network_methods)
+            
index eb34e7c..e94b10b 100644 (file)
@@ -1,25 +1,21 @@
 #
 # Functions for interacting with the network_types table in the database
 #
-# Mark Huang <mlhuang@cs.princeton.edu>
-# Copyright (C) 2006 The Trustees of Princeton University
 #
-
+from types import StringTypes
 from PLC.Faults import *
 from PLC.Parameter import Parameter
-from PLC.Table import Row, Table
+from PLC.Storage.AlchemyObject import AlchemyObj
 
-class NetworkType(Row):
+class NetworkType(AlchemyObj):
     """
     Representation of a row in the network_types table. To use,
     instantiate with a dict of values.
     """
 
-    table_name = 'network_types'
-    primary_key = 'type'
-    join_tables = ['interfaces']
+    tablename = 'network_types'
     fields = {
-        'type': Parameter(str, "Network type", max = 20),
+        'type': Parameter(str, "Network type", max = 20, primary_key=True),
         }
 
     def validate_type(self, name):
@@ -28,24 +24,23 @@ class NetworkType(Row):
             raise PLCInvalidArgument, "Network type must be specified"
 
         # Make sure network type does not alredy exist
-        conflicts = NetworkTypes(self.api, [name])
+        conflicts = NetworkTypes(self.api, name)
         if conflicts:
             raise PLCInvalidArgument, "Network type name already in use"
 
         return name
 
-class NetworkTypes(Table):
+class NetworkTypes(list):
     """
     Representation of the network_types table in the database.
     """
 
     def __init__(self, api, types = None):
-        Table.__init__(self, api, NetworkType)
-
-        sql = "SELECT %s FROM network_types" % \
-              ", ".join(NetworkType.fields)
-
-        if types:
-            sql += " WHERE type IN (%s)" % ", ".join( [ api.db.quote (t) for t in types ] )
-
-        self.selectall(sql)
+        if not types:
+            network_types = NetworkType().select()
+        elif isinstance(types, StringTypes):
+            network_types = NetworkType().select({'type': types})
+        else:
+            raise PLCInvalidArgument, "Wrong network type filter %r"%types 
+
+        self.extend(network_types)
index bbbb6b3..1cccc28 100644 (file)
@@ -1,17 +1,14 @@
 #
 # Functions for interacting with the nodegroups table in the database
 #
-# Mark Huang <mlhuang@cs.princeton.edu>
-# Copyright (C) 2006 The Trustees of Princeton University
 #
 
 from types import StringTypes
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter, Mixed
-from PLC.Filter import Filter
 from PLC.Debug import profile
-from PLC.Table import Row, Table
+from PLC.Storage.AlchemyObject import AlchemyObj
 from PLC.Nodes import Node, Nodes
 
 class NodeGroup(Row):
@@ -21,18 +18,16 @@ class NodeGroup(Row):
     dict. Commit to the database with sync().
     """
 
-    table_name = 'nodegroups'
-    primary_key = 'nodegroup_id'
+    tablename = 'nodegroups'
     join_tables = ['conf_file_nodegroup']
-    primary_field = 'nodegroup_id'
     fields = {
-        'nodegroup_id': Parameter(int, "Node group identifier"),
+        'nodegroup_id': Parameter(int, "Node group identifier", primary_key),
         'groupname': Parameter(str, "Node group name", max = 50),
         'tag_type_id': Parameter (int, "Node tag type id"),
         'value' : Parameter(str, "value that the nodegroup definition is based upon"),
         'tagname' : Parameter(str, "Tag name that the nodegroup definition is based upon"),
-        'conf_file_ids': Parameter([int], "List of configuration files specific to this node group"),
-        'node_ids' : Parameter([int], "List of node_ids that belong to this nodegroup"),
+        'conf_file_ids': Parameter([int], "List of configuration files specific to this node group", joined=True),
+        'node_ids' : Parameter([int], "List of node_ids that belong to this nodegroup", joined=True),
         }
     related_fields = {
         }
@@ -43,68 +38,43 @@ class NodeGroup(Row):
             raise PLCInvalidArgument, "Invalid node group name"
 
         # Make sure node group does not alredy exist
-        conflicts = NodeGroups(self.api, [name])
+        conflicts = NodeGroups(self.api, name)
         for nodegroup in conflicts:
             if 'nodegroup_id' not in self or self['nodegroup_id'] != nodegroup['nodegroup_id']:
                 raise PLCInvalidArgument, "Node group name already in use"
 
         return name
 
-    def associate_conf_files(self, auth, field, value):
-        """
-        Add conf_files found in value list (AddConfFileToNodeGroup)
-        Delets conf_files not found in value list (DeleteConfFileFromNodeGroup)
-        """
+    def sync(self, commit=True, validate=True):
+        AlchemyObj.sync(self, commit, validate)
+        if 'nodegroup_id' not in self:
+            AlchemyObj.insert(self, dict(self))
+        else:
+            AlchemyObj.update(self, {'nodegroup_id': self['nodegroup_id']}, dict(self))
 
-        assert 'conf_file_ids' in self
-        assert 'nodegroup_id' in self
-        assert isinstance(value, list)
-
-        conf_file_ids = self.separate_types(value)[0]
-
-        if self['conf_file_ids'] != conf_file_ids:
-            from PLC.Methods.AddConfFileToNodeGroup import AddConfFileToNodeGroup
-            from PLC.Methods.DeleteConfFileFromNodeGroup import DeleteConfFileFromNodeGroup
-            new_conf_files = set(conf_file_ids).difference(self['conf_file_ids'])
-            stale_conf_files = set(self['conf_file_ids']).difference(conf_file_ids)
-
-            for new_conf_file in new_conf_files:
-                AddConfFileToNodeGroup.__call__(AddConfFileToNodeGroup(self.api),
-                                                auth, new_conf_file, self['nodegroup_id'])
-            for stale_conf_file in stale_conf_files:
-                DeleteConfFileFromNodeGroup.__call__(DeleteConfFileFromNodeGroup(self.api),
-                                                     auth, stale_conf_file, self['nodegroup_id'])
-
-
-class NodeGroups(Table):
+class NodeGroups(list):
     """
     Representation of row(s) from the nodegroups table in the
     database.
     """
 
     def __init__(self, api, nodegroup_filter = None, columns = None):
-        Table.__init__(self, api, NodeGroup, columns)
-
-        sql = "SELECT %s FROM view_nodegroups WHERE True" % \
-              ", ".join(self.columns)
-
-        if nodegroup_filter is not None:
-            if isinstance(nodegroup_filter, (list, tuple, set)):
-                # Separate the list into integers and strings
-                ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter)
-                strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter)
-                nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': ints, 'groupname': strs})
-                sql += " AND (%s) %s" % nodegroup_filter.sql(api, "OR")
-            elif isinstance(nodegroup_filter, dict):
-                nodegroup_filter = Filter(NodeGroup.fields, nodegroup_filter)
-                sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND")
-            elif isinstance(nodegroup_filter, (int, long)):
-                nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': nodegroup_filter})
-                sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND")
-            elif isinstance(nodegroup_filter, StringTypes):
-                nodegroup_filter = Filter(NodeGroup.fields, {'groupname': nodegroup_filter})
-                sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND")
-            else:
-                raise PLCInvalidArgument, "Wrong node group filter %r"%nodegroup_filter
 
-        self.selectall(sql)
+        if not nodegroup_filter is not None:
+            nodegroups = NodeGroup().select()
+        if isinstance(nodegroup_filter, (list, tuple, set)):
+            # Separate the list into integers and strings
+            ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter)
+            strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter)
+            nodegroups = NodeGroup().select(filter={'nodegroup_id': ints, 'groupname': strs})
+        elif isinstance(nodegroup_filter, dict):
+            nodegroups = NodeGroup().select(filter=nodegroup_filter)
+        elif isinstance(nodegroup_filter, (int, long)):
+            nodegroups = NodeGroup().select(filter={'nodegroup_id': nodegroup_filter})
+        elif isinstance(nodegroup_filter, StringTypes):
+            nodegroups = NodeGroup().select(filter={'groupname': nodegroup_filter})
+        else:
+            raise PLCInvalidArgument, "Wrong node group filter %r"%nodegroup_filter
+
+        for nodegroup in nodegroups:
+            self.append(nodegroup)