diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index d1aa37c7429551bb696b014f37916bc70a75ecc4..5a7e3fe1ae214ddf4c9fd0d27dd0bbae7fee3e54 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -3814,6 +3814,7 @@ class LUSetNodeParams(LogicalUnit):
     ("offline", None, ht.TMaybeBool),
     ("drained", None, ht.TMaybeBool),
     ("auto_promote", False, ht.TBool),
+    ("master_capable", None, ht.TMaybeBool),
     _PForce,
     ]
   REQ_BGL = False
@@ -3829,7 +3830,8 @@ class LUSetNodeParams(LogicalUnit):
 
   def CheckArguments(self):
     self.op.node_name = _ExpandNodeName(self.cfg, self.op.node_name)
-    all_mods = [self.op.offline, self.op.master_candidate, self.op.drained]
+    all_mods = [self.op.offline, self.op.master_candidate, self.op.drained,
+                self.op.master_capable]
     if all_mods.count(None) == len(all_mods):
       raise errors.OpPrereqError("Please pass at least one modification",
                                  errors.ECODE_INVAL)
@@ -3841,7 +3843,8 @@ class LUSetNodeParams(LogicalUnit):
     # Boolean value that tells us whether we might be demoting from MC
     self.might_demote = (self.op.master_candidate == False or
                          self.op.offline == True or
-                         self.op.drained == True)
+                         self.op.drained == True or
+                         self.op.master_capable == False)
 
     self.lock_all = self.op.auto_promote and self.might_demote
 
@@ -3862,6 +3865,7 @@ class LUSetNodeParams(LogicalUnit):
       "MASTER_CANDIDATE": str(self.op.master_candidate),
       "OFFLINE": str(self.op.offline),
       "DRAINED": str(self.op.drained),
+      "MASTER_CAPABLE": str(self.op.master_capable),
       }
     nl = [self.cfg.GetMasterNode(),
           self.op.node_name]
@@ -3884,6 +3888,10 @@ class LUSetNodeParams(LogicalUnit):
                                    " only via master-failover",
                                    errors.ECODE_INVAL)
 
+    if self.op.master_candidate and not node.master_capable:
+      raise errors.OpPrereqError("Node %s is not master capable, cannot make"
+                                 " it a master candidate" % node.name,
+                                 errors.ECODE_STATE)
 
     if node.master_candidate and self.might_demote and not self.lock_all:
       assert not self.op.auto_promote, "auto-promote set but lock_all not"
@@ -3911,11 +3919,17 @@ class LUSetNodeParams(LogicalUnit):
     # away from the respective state, as only real changes are kept
 
     # If we're being deofflined/drained, we'll MC ourself if needed
-    if self.op.drained == False or self.op.offline == False:
+    if (self.op.drained == False or self.op.offline == False or
+        (self.op.master_capable and not node.master_capable)):
       if _DecideSelfPromotion(self):
         self.op.master_candidate = True
         self.LogInfo("Auto-promoting node to master candidate")
 
+    # If we're no longer master capable, we'll demote ourselves from MC
+    if self.op.master_capable == False and node.master_candidate:
+      self.LogInfo("Demoting from master candidate")
+      self.op.master_candidate = False
+
   def Exec(self, feedback_fn):
     """Modifies a node.
 
@@ -3942,6 +3956,10 @@ class LUSetNodeParams(LogicalUnit):
     result = []
     changed_mc = [old_role, new_role].count(self._ROLE_CANDIDATE) == 1
 
+    if self.op.master_capable is not None:
+      node.master_capable = self.op.master_capable
+      result.append(("master_capable", str(self.op.master_capable)))
+
     # Tell the node to demote itself, if no longer MC and not offline
     if (old_role == self._ROLE_CANDIDATE and
         new_role != self._ROLE_OFFLINE and new_role != old_role):
diff --git a/lib/opcodes.py b/lib/opcodes.py
index dd4e093c80a09affa4ecd58933119143f5479f8b..aadff34b622a6ef4d8addc50e9ca09b071a62da1 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -430,6 +430,7 @@ class OpSetNodeParams(OpCode):
     "offline",
     "drained",
     "auto_promote",
+    "master_capable",
     ]