diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded
index 959dcf77d63b7294668b80fdd85d803b2726bacf..10705333fdee236399252c9293433d4e34c4eff1 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 0c1f23704f97a08a246ae91cc9c7f6c1430661f0..8a5aa8cb2fd7b734c63bb3e24fcf32da0257afdd 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 6e2f41cd2498ce5bc886708fabbdd4350570eaa2..f0521aa0a239703992978e53e1f64993be2e0fa3 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 11887e443a2ff7b652786290cc6e895cfdfbf846..86a6a3ff93092f68aa863df65735c03222edeed3 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).