add pcu/node functions
[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: PCUs.py,v 1.2 2006/10/11 19:54:53 mlhuang Exp $
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 from PLC.NodeNetworks import valid_ip, NodeNetwork, NodeNetworks
15 from PLC.Nodes import Node, Nodes
16
17 class PCU(Row):
18     """
19     Representation of a row in the pcus table. To use,
20     instantiate with a dict of values.
21     """
22
23     table_name = 'pcus'
24     primary_key = 'pcu_id'
25     fields = {
26         'pcu_id': Parameter(int, "PCU identifier"),
27         'site_id': Parameter(int, "Identifier of site where PCU is located"),
28         'hostname': Parameter(str, "PCU hostname", max = 254),
29         'ip': Parameter(str, "PCU IP address", max = 254),
30         'protocol': Parameter(str, "PCU protocol, e.g. ssh, https, telnet", max = 16),
31         'username': Parameter(str, "PCU username", max = 254),
32         'password': Parameter(str, "PCU username", max = 254),
33         'notes': Parameter(str, "Miscellaneous notes", max = 254),
34         'model': Parameter(str, "PCU model string", max = 32),
35         'node_ids': Parameter([int], "List of nodes that this PCU controls", ro = True),
36         'ports': Parameter([int], "List of the port numbers that each node is connected to", ro = True),
37         }
38
39     def __init__(self, api, fields = {}):
40         Row.__init__(self, fields)
41         self.api = api
42
43     def validate_ip(self, ip):
44         if not valid_ip(ip):
45             raise PLCInvalidArgument, "Invalid IP address " + ip
46         return ip
47
48     def add_node(self, node, port, commit = True):
49         """
50         Add node to existing PCU.
51         """
52
53         assert 'pcu_id' in self
54         assert isinstance(node, Node)
55         assert isinstance(port, (int, long))
56         assert 'node_id' in node
57
58         pcu_id = self['pcu_id']
59         node_id = node['node_id']
60
61         if node_id not in self['node_ids'] and port not in self['ports']:
62             self.api.db.do("INSERT INTO pcu_node (pcu_id, node_id, port)" \
63                            " VALUES(%(pcu_id)d, %(node_id)d, %(port)d)",
64                            locals())
65
66             if commit:
67                 self.api.db.commit()
68
69             self['node_ids'].append(node_id)
70             self['ports'].append(port)
71
72     def remove_node(self, node, commit = True):
73         """
74         Remove node from existing PCU.
75         """
76
77         assert 'pcu_id' in self
78         assert isinstance(node, Node)
79         assert 'node_id' in node
80
81         pcu_id = self['pcu_id']
82         node_id = node['node_id']
83
84         if node_id in self['node_ids']:
85             i = self['node_ids'].index(node_id)
86             port = self['ports'][i]
87
88             self.api.db.do("DELETE FROM pcu_node" \
89                            " WHERE pcu_id = %(pcu_id)d" \
90                            " AND node_id = %(node_id)d",
91                            locals())
92
93             if commit:
94                 self.api.db.commit()
95
96             self['node_ids'].remove(node_id)
97             self['ports'].remove(port)
98
99     def delete(self, commit = True):
100         """
101         Delete existing PCU.
102         """
103
104         assert 'pcu_id' in self
105
106         # Clean up various join tables
107         for table in ['pcu_node', 'pcus']:
108             self.api.db.do("DELETE FROM " + table +
109                            " WHERE pcu_id = %(pcu_id)d",
110                            self)
111
112         if commit:
113             self.api.db.commit()
114
115 class PCUs(Table):
116     """
117     Representation of row(s) from the pcus table in the
118     database.
119     """
120
121     def __init__(self, api, pcu_ids = None):
122         self.api = api
123
124         # N.B.: Node IDs returned may be deleted.
125         sql = "SELECT %s FROM view_pcus" % \
126               ", ".join(PCU.fields)
127
128         if pcu_ids:
129             sql += " WHERE pcu_id IN (%s)" % ", ".join(map(str, pcu_ids))
130
131         rows = self.api.db.selectall(sql)
132
133         for row in rows:
134             self[row['pcu_id']] = pcu = PCU(api, row)
135             for aggregate in ['node_ids', 'ports']:
136                 if not pcu.has_key(aggregate) or pcu[aggregate] is None:
137                     pcu[aggregate] = []
138                 else:
139                     pcu[aggregate] = map(int, pcu[aggregate].split(','))