Initial checkin of new API implementation
[plcapi.git] / PLC / PCUs.py
1 #
2 # Functions for interacting with the pcus 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 PLC.Faults import *
11 from PLC.Parameter import Parameter
12 from PLC.Debug import profile
13 from PLC.Table import Row, Table
14
15 class PCU(Row):
16     """
17     Representation of a row in the pcu table. To use,
18     instantiate with a dict of values.
19     """
20
21     fields = {
22         'pcu_id': Parameter(int, "Node group identifier"),
23         'hostname': Parameter(str, "Fully qualified hostname"),
24         }
25
26     # These fields are derived from join tables and are not
27     # actually in the pcu table.
28     join_fields = {
29         'node_ids': Parameter([int], "List of nodes that this PCU controls"),
30         }
31
32     def __init__(self, api, fields):
33         Row.__init__(self, fields)
34         self.api = api
35
36     def flush(self, commit = True):
37         """
38         Commit changes back to the database.
39         """
40
41         self.validate()
42
43         # Fetch a new pcu_id if necessary
44         if 'pcu_id' not in self:
45             rows = self.api.db.selectall("SELECT NEXTVAL('pcu_pcu_id_seq') AS pcu_id")
46             if not rows:
47                 raise PLCDBError, "Unable to fetch new pcu_id"
48             self['pcu_id'] = rows[0]['pcu_id']
49             insert = True
50         else:
51             insert = False
52
53         # Filter out unknown fields
54         fields = dict(filter(lambda (key, value): key in self.fields,
55                              self.items()))
56
57         # Parameterize for safety
58         keys = fields.keys()
59         values = [self.api.db.param(key, value) for (key, value) in fields.items()]
60
61         if insert:
62             # Insert new row in pcu table
63             sql = "INSERT INTO pcu (%s) VALUES (%s)" % \
64                   (", ".join(keys), ", ".join(values))
65         else:
66             # Update existing row in sites table
67             columns = ["%s = %s" % (key, value) for (key, value) in zip(keys, values)]
68             sql = "UPDATE pcu SET " + \
69                   ", ".join(columns) + \
70                   " WHERE pcu_id = %(pcu_id)d"
71
72         self.api.db.do(sql, fields)
73
74         if commit:
75             self.api.db.commit()
76
77     def delete(self, commit = True):
78         """
79         Delete existing PCU.
80         """
81
82         assert 'pcu_id' in self
83
84         # Delete ourself
85         for table in ['pcu_ports', 'pcu']:
86             self.api.db.do("DELETE FROM %s" \
87                            " WHERE nodenetwork_id = %(pcu_id)" % \
88                            table, self)
89
90         if commit:
91             self.api.db.commit()
92
93 class PCUs(Table):
94     """
95     Representation of row(s) from the pcu table in the
96     database.
97     """
98
99     def __init__(self, api, pcu_id_or_hostname_list = None):
100         self.api = api
101
102         # N.B.: Node IDs returned may be deleted.
103         sql = "SELECT pcu.*, pcu_ports.node_id" \
104               " FROM pcu" \
105               " LEFT JOIN pcu_ports USING (pcu_id)"
106
107         if pcu_id_or_hostname_list:
108             # Separate the list into integers and strings
109             pcu_ids = filter(lambda pcu_id: isinstance(pcu_id, (int, long)),
110                                    pcu_id_or_hostname_list)
111             hostnames = filter(lambda hostname: isinstance(hostname, StringTypes),
112                            pcu_id_or_hostname_list)
113             sql += " AND (False"
114             if pcu_ids:
115                 sql += " OR pcu_id IN (%s)" % ", ".join(map(str, pcu_ids))
116             if hostnames:
117                 sql += " OR hostname IN (%s)" % ", ".join(api.db.quote(hostnames)).lower()
118             sql += ")"
119
120         rows = self.api.db.selectall(sql, locals())
121         for row in rows:
122             if self.has_key(row['pcu_id']):
123                 pcu = self[row['pcu_id']]
124                 pcu.update(row)
125             else:
126                 self[row['pcu_id']] = PCU(api, row)