From 56aa9fd555ab30d0a002a239c6a5d7a88692c58e Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Fri, 5 Dec 2008 03:01:21 +0000
Subject: [PATCH] Cleanup the config file on demotion from candidate

This patch adds a simple rpc which makes a backup of the config file and
then removes it. This is done so that cluster verify doesn't complain
immediately after demoting a node.

Reviewed-by: imsnah
---
 daemons/ganeti-noded |  8 ++++++++
 lib/backend.py       | 20 ++++++++++++++++++++
 lib/cmdlib.py        |  7 +++++++
 lib/rpc.py           |  8 ++++++++
 4 files changed, 43 insertions(+)

diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded
index 959dcf77d..10705333f 100755
--- a/daemons/ganeti-noded
+++ b/daemons/ganeti-noded
@@ -472,6 +472,14 @@ class NodeHttpServer(http.server.HttpServer):
     """
     return backend.NodeVolumes()
 
+  @staticmethod
+  def perspective_node_demote_from_mc(params):
+    """Demote a node from the master candidate role.
+
+    """
+    return backend.DemoteFromMC()
+
+
   # cluster --------------------------
 
   @staticmethod
diff --git a/lib/backend.py b/lib/backend.py
index 0c1f23704..8a5aa8cb2 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -2051,6 +2051,26 @@ def ValidateHVParams(hvname, hvparams):
     return (False, str(err))
 
 
+def DemoteFromMC():
+  """Demotes the current node from master candidate role.
+
+  """
+  # try to ensure we're not the master by mistake
+  master, myself = ssconf.GetMasterAndMyself()
+  if master == myself:
+    return (False, "ssconf status shows I'm the master node, will not demote")
+  pid_file = utils.DaemonPidFileName(constants.MASTERD_PID)
+  if utils.IsProcessAlive(utils.ReadPidFile(pid_file)):
+    return (False, "The master daemon is running, will not demote")
+  try:
+    utils.CreateBackup(constants.CLUSTER_CONF_FILE)
+  except EnvironmentError, err:
+    if err.errno != errno.ENOENT:
+      return (False, "Error while backing up cluster file: %s" % str(err))
+  utils.RemoveFile(constants.CLUSTER_CONF_FILE)
+  return (True, "Done")
+
+
 class HooksRunner(object):
   """Hook runner.
 
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 6e2f41cd2..f0521aa0a 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -2157,6 +2157,13 @@ class LUSetNodeParams(LogicalUnit):
     if self.op.master_candidate is not None:
       node.master_candidate = self.op.master_candidate
       result.append(("master_candidate", str(self.op.master_candidate)))
+      if self.op.master_candidate == False:
+        rrc = self.rpc.call_node_demote_from_mc(node.name)
+        if (rrc.failed or not isinstance(rrc.data, (tuple, list))
+            or len(rrc.data) != 2):
+          self.LogWarning("Node rpc error: %s" % rrc.error)
+        elif not rrc.data[0]:
+          self.LogWarning("Node failed to demote itself: %s" % rrc.data[1])
 
     # this will trigger configuration file update, if needed
     self.cfg.Update(node)
diff --git a/lib/rpc.py b/lib/rpc.py
index 11887e443..86a6a3ff9 100644
--- a/lib/rpc.py
+++ b/lib/rpc.py
@@ -828,6 +828,14 @@ class RpcRunner(object):
     """
     return self._MultiNodeCall(node_list, "node_volumes", [])
 
+  def call_node_demote_from_mc(self, node):
+    """Demote a node from the master candidate role.
+
+    This is a single-node call.
+
+    """
+    return self._SingleNodeCall(node, "node_demote_from_mc", [])
+
   def call_test_delay(self, node_list, duration):
     """Sleep for a fixed time on given node(s).
 
-- 
GitLab