set svn:keywords property for proper keywords expansion
[plcapi.git] / PLC / Nodes.py
index 4c1c695..87f0d1c 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: Nodes.py,v 1.26 2006/11/28 14:55:00 thierry Exp $
+# $Id$
 #
 
 from types import StringTypes
@@ -38,7 +38,8 @@ class Node(Row):
 
     table_name = 'nodes'
     primary_key = 'node_id'
-    join_tables = ['nodegroup_node', 'conf_file_node', 'nodenetworks', 'pcu_node', 'slice_node', 'slice_attribute', 'node_session']
+    # Thierry -- we use delete on nodenetworks so the related NodeNetworkSettings get deleted too
+    join_tables = ['nodegroup_node', 'conf_file_node', 'pcu_node', 'slice_node', 'slice_attribute', 'node_session', 'peer_node','node_slice_whitelist']
     fields = {
         'node_id': Parameter(int, "Node identifier"),
         'hostname': Parameter(str, "Fully qualified hostname", max = 255),
@@ -50,6 +51,7 @@ class Node(Row):
         'ssh_rsa_key': Parameter(str, "Last known SSH host key", max = 1024),
         'date_created': Parameter(int, "Date and time when node entry was created", ro = True),
         'last_updated': Parameter(int, "Date and time when node entry was created", ro = True),
+       'last_contact': Parameter(int, "Date and time when node last contacted plc", ro = True), 
         'key': Parameter(str, "(Admin only) Node key", max = 256),
         'session': Parameter(str, "(Admin only) Node session value", max = 256, ro = True),
         'nodenetwork_ids': Parameter([int], "List of network interfaces that this node has"),
@@ -57,14 +59,19 @@ class Node(Row):
         'conf_file_ids': Parameter([int], "List of configuration files specific to this node"),
         # 'root_person_ids': Parameter([int], "(Admin only) List of people who have root access to this node"),
         'slice_ids': Parameter([int], "List of slices on this node"),
+       'slice_ids_whitelist': Parameter([int], "List of slices allowed on this node"),
         'pcu_ids': Parameter([int], "List of PCUs that control this node"),
         'ports': Parameter([int], "List of PCU ports that this node is connected to"),
-        'peer_id': Parameter(int, "Peer at which this node is managed", nullok = True),
+        'peer_id': Parameter(int, "Peer to which this node belongs", nullok = True),
+        'peer_node_id': Parameter(int, "Foreign node identifier at peer", nullok = True),
         }
 
     # for Cache
     class_key = 'hostname'
-    foreign_fields = ['boot_state','model','version','date_created','last_updated']
+    foreign_fields = ['boot_state','model','version']
+    # forget about these ones, they are read-only anyway
+    # handling them causes Cache to re-sync all over again 
+    # 'date_created','last_updated'
     foreign_xrefs = [
        # in this case, we dont need the 'table' but Cache will look it up, so...
         {'field' : 'site_id' , 'class' : 'Site' , 'table' : 'unused-on-direct-refs' } ,
@@ -88,11 +95,34 @@ class Node(Row):
 
         return boot_state
 
-    # timestamps
-    def validate_date_created (self, timestamp):
-       return self.validate_timestamp (timestamp)
-    def validate_last_updated (self, timestamp):
-       return self.validate_timestamp (timestamp)
+    validate_date_created = Row.validate_timestamp
+    validate_last_updated = Row.validate_timestamp
+    validate_last_contact = Row.validate_timestamp
+
+    def update_last_contact(self, commit = True):
+       """
+       Update last_contact field with current time
+       """
+       
+       assert 'node_id' in self
+       assert self.table_name
+
+       self.api.db.do("UPDATE %s SET last_contact = CURRENT_TIMESTAMP " % (self.table_name) + \
+                      " where node_id = %d" % ( self['node_id']) )
+       self.sync(commit)
+
+
+    def update_last_updated(self, commit = True):
+        """
+        Update last_updated field with current time
+        """
+
+        assert 'node_id' in self
+        assert self.table_name
+
+        self.api.db.do("UPDATE %s SET last_updated = CURRENT_TIMESTAMP " % (self.table_name) + \
+                       " where node_id = %d" % (self['node_id']) )
+        self.sync(commit)
 
     def delete(self, commit = True):
         """
@@ -100,6 +130,11 @@ class Node(Row):
         """
 
         assert 'node_id' in self
+       assert 'nodenetwork_ids' in self
+
+       # we need to clean up NodeNetworkSettings, so handling nodenetworks as part of join_tables does not work
+       for nodenetwork in NodeNetworks(self.api,self['nodenetwork_ids']):
+           nodenetwork.delete()
 
         # Clean up miscellaneous join tables
         for table in self.join_tables:
@@ -129,10 +164,17 @@ class Nodes(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), node_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), node_filter)
                 node_filter = Filter(Node.fields, {'node_id': ints, 'hostname': strs})
-                sql += " AND (%s)" % node_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % node_filter.sql(api, "OR")
             elif isinstance(node_filter, dict):
                 node_filter = Filter(Node.fields, node_filter)
-                sql += " AND (%s)" % node_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % node_filter.sql(api, "AND")
+            elif isinstance (node_filter, StringTypes):
+                node_filter = Filter(Node.fields, {'hostname':[node_filter]})
+                sql += " AND (%s) %s" % node_filter.sql(api, "AND")
+            elif isinstance (node_filter, int):
+                node_filter = Filter(Node.fields, {'node_id':[node_filter]})
+                sql += " AND (%s) %s" % node_filter.sql(api, "AND")
+            else:
+                raise PLCInvalidArgument, "Wrong node filter %r"%node_filter
 
         self.selectall(sql)
-