Add new capability to API for a node to report its current runlevel.
authorStephen Soltesz <soltesz@cs.princeton.edu>
Wed, 18 Feb 2009 23:45:26 +0000 (23:45 +0000)
committerStephen Soltesz <soltesz@cs.princeton.edu>
Wed, 18 Feb 2009 23:45:26 +0000 (23:45 +0000)
Additional motivation is available in message to devel@lists.planet-lab.org:
http://lists.planet-lab.org/pipermail/devel/2009-February/003283.html

Briefly:
this patch differentiates between boot_states (declared by user) and
run_levels (reported by node) a user would specify that the node should be
in 'boot' or 'reinstall', and the node will report what state it is in,
i.e, it is installing, or it has failed to boot, or it is in boot.

because updates are continuous, other service routines can get involved to notify
admins, users, or automated scripts when the values are out-of-sync.

PLC/Methods/ReportRunlevel.py [new file with mode: 0644]
PLC/Methods/__init__.py
PLC/Nodes.py
migrations/v4-to-v5/migrate.sql
planetlab5.sql

diff --git a/PLC/Methods/ReportRunlevel.py b/PLC/Methods/ReportRunlevel.py
new file mode 100644 (file)
index 0000000..d1cdf39
--- /dev/null
@@ -0,0 +1,51 @@
+# $Id$
+from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.Auth import Auth, BootAuth, SessionAuth
+from PLC.Nodes import Node, Nodes
+
+can_update = ['run_level', 'extrainfo']
+
+class ReportRunlevel(Method):
+    """
+        report runlevel
+    """
+    roles = ['node', 'admin']
+
+    accepts = [
+        Mixed(BootAuth(), SessionAuth(), Auth()),
+        {'run_level': Node.fields['run_level'],
+         'extrainfo': Node.fields['extrainfo'],
+         },
+        Mixed(Node.fields['node_id'],
+              Node.fields['hostname'])
+        ]
+
+    returns = Parameter(int, '1 if successful')
+
+    def call(self, auth, report_fields, node_id_or_hostname=None):
+
+        if not isinstance(self.caller, Node):
+            # check admin
+            if 'admin' not in self.caller['roles']:
+                raise PLCPermissionDenied, "Not allowed to update node run_level"
+
+            nodes = Nodes(self.api, [node_id_or_hostname])
+            if not nodes:
+                raise PLCInvalidArgument, "No such node"
+        else:
+            nodes  = [self.caller]
+
+        node = nodes[0]
+
+        node.update_last_contact()
+        for field in can_update:
+            if field in report_fields:
+                node.update({field : report_fields[field]})
+
+        node.sync(commit=True)
+
+        self.message = "Node Runlevel Report : %s" % ", ".join(report_fields.keys())
+
+        return 1
index 3a987da..2dd3f96 100644 (file)
@@ -128,6 +128,7 @@ NotifySupport
 RebootNode
 RebootNodeWithPCU
 RefreshPeer
+ReportRunlevel
 ResetPassword
 SetPersonPrimarySite
 SliceCreate
index 20bc621..f25a617 100644 (file)
@@ -48,6 +48,8 @@ class Node(Row):
         'hostname': Parameter(str, "Fully qualified hostname", max = 255),
         'site_id': Parameter(int, "Site at which this node is located"),
         'boot_state': Parameter(str, "Boot state", max = 20),
+        'run_level': Parameter(str, "Run level", max = 20),
+        'extrainfo': Parameter(str, "Extra information about the host", max = 256),
         'model': Parameter(str, "Make and model of the actual machine", max = 255, nullok = True),
         'boot_nonce': Parameter(str, "(Admin only) Random value generated by the node at last boot", max = 128),
         'version': Parameter(str, "Apparent Boot CD version", max = 64),
@@ -55,6 +57,7 @@ class Node(Row):
         '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), 
+        'verified': Parameter(bool, "Whether the node configuration is verified correct", ro=False),
         'key': Parameter(str, "(Admin only) Node key", max = 256),
         'session': Parameter(str, "(Admin only) Node session value", max = 256, ro = True),
         'interface_ids': Parameter([int], "List of network interfaces that this node has"),
index 99b72bc..a7f71fd 100644 (file)
@@ -111,6 +111,9 @@ ALTER TABLE peers ADD COLUMN hrn_root TEXT;
 -- nodes
 ----------------------------------------
 ALTER TABLE nodes ADD COLUMN node_type TEXT NOT NULL DEFAULT 'regular';
+ALTER TABLE nodes ADD COLUMN verified boolean NOT NULL DEFAULT false;  -- whether or not the node & pcu are verified
+ALTER TABLE nodes ADD COLUMN extrainfo TEXT;
+ALTER TABLE nodes ADD COLUMN run_level TEXT REFERENCES run_levels DEFAULT NULL; -- Node Run Level
 
 ----------------------------------------
 -- tag types
@@ -237,6 +240,17 @@ drop view mgn_nodegroups;
 drop table mgn_site_nodegroup;
 drop table nodegroup_node;
 
+----------------------------------------
+-- run levels
+----------------------------------------
+CREATE TABLE run_levels  (
+    run_level text PRIMARY KEY
+) WITH OIDS;
+INSERT INTO run_levels  (run_level) VALUES ('boot');
+INSERT INTO run_levels  (run_level) VALUES ('safeboot');
+INSERT INTO run_levels  (run_level) VALUES ('failboot');
+INSERT INTO run_levels  (run_level) VALUES ('reinstall');
+
 ----------------------------------------
 -- boot states
 ----------------------------------------
@@ -244,22 +258,23 @@ drop table nodegroup_node;
 INSERT INTO boot_states (boot_state) VALUES ('safeboot');
 INSERT INTO boot_states (boot_state) VALUES ('failboot');
 INSERT INTO boot_states (boot_state) VALUES ('disabled');
-INSERT INTO boot_states (boot_state) VALUES ('install');
 INSERT INTO boot_states (boot_state) VALUES ('reinstall');
 
 -- map old ones
-UPDATE nodes SET boot_state='failboot' WHERE boot_state='dbg';
+-- b/c boot_states are declared by users not reported by node.
+UPDATE nodes SET boot_state='safeboot' WHERE boot_state='dbg';  
 UPDATE nodes SET boot_state='safeboot' WHERE boot_state='diag';
 UPDATE nodes SET boot_state='disabled' WHERE boot_state='disable';
-UPDATE nodes SET boot_state='install' WHERE boot_state='inst';
+UPDATE nodes SET boot_state='reinstall' WHERE boot_state='inst';
 UPDATE nodes SET boot_state='reinstall' WHERE boot_state='rins';
 UPDATE nodes SET boot_state='reinstall' WHERE boot_state='new';
-UPDATE nodes SET boot_state='failboot' WHERE boot_state='rcnf';
+UPDATE nodes SET boot_state='reinstall' WHERE boot_state='rcnf';
 
 -- delete old ones
 DELETE FROM boot_states WHERE boot_state='dbg';
 DELETE FROM boot_states WHERE boot_state='diag';
 DELETE FROM boot_states WHERE boot_state='disable';
+DELETE FROM boot_states WHERE boot_state='install';
 DELETE FROM boot_states WHERE boot_state='inst';
 DELETE FROM boot_states WHERE boot_state='rins';
 DELETE FROM boot_states WHERE boot_state='new';
index 6c4cc98..411003a 100644 (file)
@@ -259,10 +259,16 @@ CREATE TABLE boot_states (
 ) WITH OIDS;
 INSERT INTO boot_states (boot_state) VALUES ('boot');
 INSERT INTO boot_states (boot_state) VALUES ('safeboot');
-INSERT INTO boot_states (boot_state) VALUES ('failboot');
-INSERT INTO boot_states (boot_state) VALUES ('disabled');
-INSERT INTO boot_states (boot_state) VALUES ('install');
 INSERT INTO boot_states (boot_state) VALUES ('reinstall');
+INSERT INTO boot_states (boot_state) VALUES ('disabled');
+
+CREATE TABLE run_levels  (
+    run_level text PRIMARY KEY
+) WITH OIDS;
+INSERT INTO run_levels  (run_level) VALUES ('boot');
+INSERT INTO run_levels  (run_level) VALUES ('safeboot');
+INSERT INTO run_levels  (run_level) VALUES ('failboot');
+INSERT INTO run_levels  (run_level) VALUES ('reinstall');
 
 -- Known node types (Nodes.py expect max length to be 20)
 CREATE TABLE node_types (
@@ -281,7 +287,8 @@ CREATE TABLE nodes (
     hostname text NOT NULL,                            -- Node hostname
     site_id integer REFERENCES sites NOT NULL,         -- At which site 
     boot_state text REFERENCES boot_states NOT NULL    -- Node boot state
-              DEFAULT 'install', 
+              DEFAULT 'reinstall', 
+    run_level  text REFERENCES run_levels DEFAULT NULL, -- Node Run Level
     deleted boolean NOT NULL DEFAULT false,            -- Is deleted
 
     -- Optional
@@ -290,6 +297,8 @@ CREATE TABLE nodes (
     version text,                                      -- Boot CD version string updated by Boot Manager
     ssh_rsa_key text,                                  -- SSH host key updated by Boot Manager
     key text,                                          -- Node key generated when boot file is downloaded
+       verified boolean NOT NULL DEFAULT false,                -- whether or not the node & pcu are verified
+       extrainfo text,
 
     -- Timestamps
     date_created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -1076,10 +1085,13 @@ nodes.node_type,
 nodes.hostname,
 nodes.site_id,
 nodes.boot_state,
+nodes.run_level,
 nodes.deleted,
 nodes.model,
 nodes.boot_nonce,
 nodes.version,
+nodes.verified,
+nodes.extrainfo,
 nodes.ssh_rsa_key,
 nodes.key,
 CAST(date_part('epoch', nodes.date_created) AS bigint) AS date_created,