first draft for node tags & new node groups:
[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, Mixed
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         'tag_name' : Parameter(str, "Tag name that the nodegroup definition is based upon"),
33         'tag_value' : Parameter(str, "value that the nodegroup definition is based upon"),
34 #        'node_ids': Parameter([int], "List of nodes in this node group"),
35 #        'conf_file_ids': Parameter([int], "List of configuration files specific to this node group"),
36         }
37     related_fields = {
38         'conf_files': [Parameter(int, "ConfFile identifier")],
39         }
40
41     def validate_name(self, name):
42         # Make sure name is not blank
43         if not len(name):
44                 raise PLCInvalidArgument, "Invalid node group name"
45         
46         # Make sure node group does not alredy exist
47         conflicts = NodeGroups(self.api, [name])
48         for nodegroup in conflicts:
49             if 'nodegroup_id' not in self or self['nodegroup_id'] != nodegroup['nodegroup_id']:
50                raise PLCInvalidArgument, "Node group name already in use"
51
52         return name
53
54     def associate_conf_files(self, auth, field, value):
55         """
56         Add conf_files found in value list (AddConfFileToNodeGroup)
57         Delets conf_files not found in value list (DeleteConfFileFromNodeGroup)
58         """
59
60         assert 'conf_file_ids' in self
61         assert 'nodegroup_id' in self
62         assert isinstance(value, list)
63
64         conf_file_ids = self.separate_types(value)[0]
65
66         if self['conf_file_ids'] != conf_file_ids:
67             from PLC.Methods.AddConfFileToNodeGroup import AddConfFileToNodeGroup
68             from PLC.Methods.DeleteConfFileFromNodeGroup import DeleteConfFileFromNodeGroup
69             new_conf_files = set(conf_file_ids).difference(self['conf_file_ids'])
70             stale_conf_files = set(self['conf_file_ids']).difference(conf_file_ids)
71
72             for new_conf_file in new_conf_files:
73                 AddConfFileToNodeGroup.__call__(AddConfFileToNodeGroup(self.api), auth, new_conf_file, self['nodegroup_id'])
74             for stale_conf_file in stale_conf_files:
75                 DeleteConfFileFromNodeGroup.__call__(DeleteConfFileFromNodeGroup(self.api), auth, stale_conf_file, self['nodegroup_id'])
76
77
78 class NodeGroups(Table):
79     """
80     Representation of row(s) from the nodegroups table in the
81     database.
82     """
83
84     def __init__(self, api, nodegroup_filter = None, columns = None):
85         Table.__init__(self, api, NodeGroup, columns)
86
87         sql = "SELECT %s FROM view_nodegroups WHERE True" % \
88               ", ".join(self.columns)
89
90         if nodegroup_filter is not None:
91             if isinstance(nodegroup_filter, (list, tuple, set)):
92                 # Separate the list into integers and strings
93                 ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter)
94                 strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter)
95                 nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': ints, 'name': strs})
96                 sql += " AND (%s) %s" % nodegroup_filter.sql(api, "OR")
97             elif isinstance(nodegroup_filter, dict):
98                 nodegroup_filter = Filter(NodeGroup.fields, nodegroup_filter)
99                 sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND")
100
101         self.selectall(sql)