From 2f5da28a4da55d86f5240ce0c616107a4444ab74 Mon Sep 17 00:00:00 2001 From: Stephen Soltesz Date: Wed, 18 Feb 2009 23:45:26 +0000 Subject: [PATCH] Add new capability to API for a node to report its current runlevel. 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 | 51 +++++++++++++++++++++++++++++++++ PLC/Methods/__init__.py | 1 + PLC/Nodes.py | 3 ++ migrations/v4-to-v5/migrate.sql | 23 ++++++++++++--- planetlab5.sql | 20 ++++++++++--- 5 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 PLC/Methods/ReportRunlevel.py diff --git a/PLC/Methods/ReportRunlevel.py b/PLC/Methods/ReportRunlevel.py new file mode 100644 index 0000000..d1cdf39 --- /dev/null +++ b/PLC/Methods/ReportRunlevel.py @@ -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 diff --git a/PLC/Methods/__init__.py b/PLC/Methods/__init__.py index 3a987da..2dd3f96 100644 --- a/PLC/Methods/__init__.py +++ b/PLC/Methods/__init__.py @@ -128,6 +128,7 @@ NotifySupport RebootNode RebootNodeWithPCU RefreshPeer +ReportRunlevel ResetPassword SetPersonPrimarySite SliceCreate diff --git a/PLC/Nodes.py b/PLC/Nodes.py index 20bc621..f25a617 100644 --- a/PLC/Nodes.py +++ b/PLC/Nodes.py @@ -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"), diff --git a/migrations/v4-to-v5/migrate.sql b/migrations/v4-to-v5/migrate.sql index 99b72bc..a7f71fd 100644 --- a/migrations/v4-to-v5/migrate.sql +++ b/migrations/v4-to-v5/migrate.sql @@ -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'; diff --git a/planetlab5.sql b/planetlab5.sql index 6c4cc98..411003a 100644 --- a/planetlab5.sql +++ b/planetlab5.sql @@ -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, -- 2.43.0