more python3, esp. in shebangs and doc
[plcapi.git] / PLC / NodeGroups.py
index 35746a3..8f0a13e 100644 (file)
@@ -4,13 +4,12 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: NodeGroups.py,v 1.11 2006/10/03 19:25:30 mlhuang Exp $
-#
 
 from types import StringTypes
 
 from PLC.Faults import *
 
 from types import StringTypes
 
 from PLC.Faults import *
-from PLC.Parameter import Parameter
+from PLC.Parameter import Parameter, Mixed
+from PLC.Filter import Filter
 from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.Nodes import Node, Nodes
 from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.Nodes import Node, Nodes
@@ -24,99 +23,58 @@ class NodeGroup(Row):
 
     table_name = 'nodegroups'
     primary_key = 'nodegroup_id'
 
     table_name = 'nodegroups'
     primary_key = 'nodegroup_id'
+    join_tables = ['conf_file_nodegroup']
+    primary_field = 'nodegroup_id'
     fields = {
         'nodegroup_id': Parameter(int, "Node group identifier"),
     fields = {
         'nodegroup_id': Parameter(int, "Node group identifier"),
-        'name': Parameter(str, "Node group name", max = 50),
-        'description': Parameter(str, "Node group description", max = 200),
-        'node_ids': Parameter([int], "List of nodes in this node group"),
+        '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"),
+        }
+    related_fields = {
         }
         }
-
-    def __init__(self, api, fields = {}):
-        Row.__init__(self, fields)
-        self.api = api
 
     def validate_name(self, name):
 
     def validate_name(self, name):
-       # Remove leading and trailing spaces
-       name = name.strip()
-
-       # Make sure name is not blank after we removed the spaces
-        if not len(name) > 0:
-                raise PLCInvalidArgument, "Invalid node group name"
-       
-       # Make sure node group does not alredy exist
-       conflicts = NodeGroups(self.api, [name])
-       for nodegroup_id in conflicts:
-            if 'nodegroup_id' not in self or self['nodegroup_id'] != nodegroup_id:
-               raise PLCInvalidArgument, "Node group name already in use"
-
-       return name
-
-    def add_node(self, node, commit = True):
-        """
-        Add node to existing nodegroup.
-        """
-
-        assert 'nodegroup_id' in self
-        assert isinstance(node, Node)
-        assert 'node_id' in node
-
-        node_id = node['node_id']
-        nodegroup_id = self['nodegroup_id']
-
-        if node_id not in self['node_ids']:
-            assert nodegroup_id not in node['nodegroup_ids']
+        # Make sure name is not blank
+        if not len(name):
+            raise PLCInvalidArgument("Invalid node group name")
 
 
-            self.api.db.do("INSERT INTO nodegroup_node (nodegroup_id, node_id)" \
-                           " VALUES(%(nodegroup_id)d, %(node_id)d)",
-                           locals())
+        # Make sure node group does not alredy exist
+        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")
 
 
-            if commit:
-                self.api.db.commit()
+        return name
 
 
-            self['node_ids'].append(node_id)
-            node['nodegroup_ids'].append(nodegroup_id)
-
-    def remove_node(self, node, commit = True):
+    def associate_conf_files(self, auth, field, value):
         """
         """
-        Remove node from existing nodegroup.
+        Add conf_files found in value list (AddConfFileToNodeGroup)
+        Delets conf_files not found in value list (DeleteConfFileFromNodeGroup)
         """
 
         """
 
+        assert 'conf_file_ids' in self
         assert 'nodegroup_id' in self
         assert 'nodegroup_id' in self
-        assert isinstance(node, Node)
-        assert 'node_id' in node
-
-        node_id = node['node_id']
-        nodegroup_id = self['nodegroup_id']
-
-        if node_id in self['node_ids']:
-            assert nodegroup_id in node['nodegroup_ids']
-
-            self.api.db.do("DELETE FROM nodegroup_node" \
-                           " WHERE nodegroup_id = %(nodegroup_id)d" \
-                           " AND node_id = %(node_id)d",
-                           locals())
-
-            if commit:
-                self.api.db.commit()
+        assert isinstance(value, list)
 
 
-            self['node_ids'].remove(node_id)
-            node['nodegroup_ids'].remove(nodegroup_id)
+        conf_file_ids = self.separate_types(value)[0]
 
 
-    def delete(self, commit = True):
-        """
-        Delete existing nodegroup from the database.
-        """
-
-        assert 'nodegroup_id' in self
+        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)
 
 
-        # Clean up miscellaneous join tables
-        for table in ['nodegroup_node', 'nodegroups']:
-            self.api.db.do("DELETE FROM %s" \
-                           " WHERE nodegroup_id = %d" % \
-                           (table, self['nodegroup_id']), self)
+            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'])
 
 
-        if commit:
-            self.api.db.commit()
 
 class NodeGroups(Table):
     """
 
 class NodeGroups(Table):
     """
@@ -124,31 +82,29 @@ class NodeGroups(Table):
     database.
     """
 
     database.
     """
 
-    def __init__(self, api, nodegroup_id_or_name_list = None):
-       self.api = api
-
-        sql = "SELECT %s FROM view_nodegroups" % \
-              ", ".join(NodeGroup.fields)
-
-        if nodegroup_id_or_name_list:
-            # Separate the list into integers and strings
-            nodegroup_ids = filter(lambda nodegroup_id: isinstance(nodegroup_id, (int, long)),
-                                   nodegroup_id_or_name_list)
-            names = filter(lambda name: isinstance(name, StringTypes),
-                           nodegroup_id_or_name_list)
-            sql += " WHERE (False"
-            if nodegroup_ids:
-                sql += " OR nodegroup_id IN (%s)" % ", ".join(map(str, nodegroup_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['nodegroup_id']] = nodegroup = NodeGroup(api, row)
-            for aggregate in ['node_ids']:
-                if not nodegroup.has_key(aggregate) or nodegroup[aggregate] is None:
-                    nodegroup[aggregate] = []
-                else:
-                    nodegroup[aggregate] = map(int, nodegroup[aggregate].split(','))
+    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 = [x for x in nodegroup_filter if isinstance(x, int)]
+                strs = [x for x in nodegroup_filter if isinstance(x, StringTypes)]
+                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):
+                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)