set svn:keywords property for proper keywords expansion
[plcapi.git] / PLC / NodeGroups.py
1 #
2 # Functions for interacting with the nodegroups table in the database
3 #
4 # Mark Huang <mlhuang@cs.princeton.edu>
5 # Copyright (C) 2006 The Trustees of Princeton University
6 #
7 # $Id$
8 #
9
10 from types import StringTypes
11
12 from PLC.Faults import *
13 from PLC.Parameter import Parameter
14 from PLC.Filter import Filter
15 from PLC.Debug import profile
16 from PLC.Table import Row, Table
17 from PLC.Nodes import Node, Nodes
18
19 class NodeGroup(Row):
20     """
21     Representation of a row in the nodegroups table. To use, optionally
22     instantiate with a dict of values. Update as you would a
23     dict. Commit to the database with sync().
24     """
25
26     table_name = 'nodegroups'
27     primary_key = 'nodegroup_id'
28     join_tables = ['nodegroup_node', 'conf_file_nodegroup']
29     fields = {
30         'nodegroup_id': Parameter(int, "Node group identifier"),
31         'name': Parameter(str, "Node group name", max = 50),
32         'description': Parameter(str, "Node group description", max = 200, nullok = True),
33         'node_ids': Parameter([int], "List of nodes in this node group"),
34         'conf_file_ids': Parameter([int], "List of configuration files specific to this node group"),
35         }
36
37     def validate_name(self, name):
38         # Make sure name is not blank
39         if not len(name):
40                 raise PLCInvalidArgument, "Invalid node group name"
41         
42         # Make sure node group does not alredy exist
43         conflicts = NodeGroups(self.api, [name])
44         for nodegroup_id in conflicts:
45             if 'nodegroup_id' not in self or self['nodegroup_id'] != nodegroup_id:
46                raise PLCInvalidArgument, "Node group name already in use"
47
48         return name
49
50     def add_node(self, node, commit = True):
51         """
52         Add node to existing nodegroup.
53         """
54
55         assert 'nodegroup_id' in self
56         assert isinstance(node, Node)
57         assert 'node_id' in node
58
59         node_id = node['node_id']
60         nodegroup_id = self['nodegroup_id']
61
62         if node_id not in self['node_ids']:
63             assert nodegroup_id not in node['nodegroup_ids']
64
65             self.api.db.do("INSERT INTO nodegroup_node (nodegroup_id, node_id)" \
66                            " VALUES(%(nodegroup_id)d, %(node_id)d)",
67                            locals())
68
69             if commit:
70                 self.api.db.commit()
71
72             self['node_ids'].append(node_id)
73             node['nodegroup_ids'].append(nodegroup_id)
74
75     def remove_node(self, node, commit = True):
76         """
77         Remove node from existing nodegroup.
78         """
79
80         assert 'nodegroup_id' in self
81         assert isinstance(node, Node)
82         assert 'node_id' in node
83
84         node_id = node['node_id']
85         nodegroup_id = self['nodegroup_id']
86
87         if node_id in self['node_ids']:
88             assert nodegroup_id in node['nodegroup_ids']
89
90             self.api.db.do("DELETE FROM nodegroup_node" \
91                            " WHERE nodegroup_id = %(nodegroup_id)d" \
92                            " AND node_id = %(node_id)d",
93                            locals())
94
95             if commit:
96                 self.api.db.commit()
97
98             self['node_ids'].remove(node_id)
99             node['nodegroup_ids'].remove(nodegroup_id)
100
101 class NodeGroups(Table):
102     """
103     Representation of row(s) from the nodegroups table in the
104     database.
105     """
106
107     def __init__(self, api, nodegroup_filter = None, columns = None):
108         Table.__init__(self, api, NodeGroup, columns)
109
110         sql = "SELECT %s FROM view_nodegroups WHERE True" % \
111               ", ".join(self.columns)
112
113         if nodegroup_filter is not None:
114             if isinstance(nodegroup_filter, (list, tuple, set)):
115                 # Separate the list into integers and strings
116                 ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter)
117                 strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter)
118                 nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': ints, 'name': strs})
119                 sql += " AND (%s) %s" % nodegroup_filter.sql(api, "OR")
120             elif isinstance(nodegroup_filter, dict):
121                 nodegroup_filter = Filter(NodeGroup.fields, nodegroup_filter)
122                 sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND")
123
124         self.selectall(sql)