diff --git a/lib/backend.py b/lib/backend.py
index 86dc2ddcbe63db2d3b6a1cf9c0c301bd2d2b6799..9996017dc5d92148b90924b5b5a58a6486787b15 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -1451,7 +1451,7 @@ def InstanceShutdown(instance, timeout):
   _RemoveBlockDevLinks(iname, instance.disks)
 
 
-def InstanceReboot(instance, reboot_type, shutdown_timeout):
+def InstanceReboot(instance, reboot_type, shutdown_timeout, reason):
   """Reboot an instance.
 
   @type instance: L{objects.Instance}
@@ -1481,12 +1481,15 @@ def InstanceReboot(instance, reboot_type, shutdown_timeout):
   if reboot_type == constants.INSTANCE_REBOOT_SOFT:
     try:
       hyper.RebootInstance(instance)
+      reason.Store(instance.name)
     except errors.HypervisorError, err:
       _Fail("Failed to soft reboot instance %s: %s", instance.name, err)
   elif reboot_type == constants.INSTANCE_REBOOT_HARD:
     try:
       InstanceShutdown(instance, shutdown_timeout)
-      return StartInstance(instance, False)
+      result = StartInstance(instance, False)
+      reason.Store(instance.name)
+      return result
     except errors.HypervisorError, err:
       _Fail("Failed to hard reboot instance %s: %s", instance.name, err)
   else:
diff --git a/lib/client/gnt_instance.py b/lib/client/gnt_instance.py
index 2553516e570a7f8a70d3fc9dcb3dfd495578b84b..c92c1bbd02510d25658126838fe48ed4fbab900c 100644
--- a/lib/client/gnt_instance.py
+++ b/lib/client/gnt_instance.py
@@ -1552,7 +1552,8 @@ commands = {
     [m_force_multi, REBOOT_TYPE_OPT, IGNORE_SECONDARIES_OPT, m_node_opt,
      m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT,
      m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
-     m_inst_tags_opt, SHUTDOWN_TIMEOUT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
+     m_inst_tags_opt, SHUTDOWN_TIMEOUT_OPT, DRY_RUN_OPT, PRIORITY_OPT,
+     REASON_OPT],
     "<instance>", "Reboots an instance"),
   "activate-disks": (
     ActivateDisks, ARGS_ONE_INSTANCE,
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 36376443f808a841f74c9b5735cab50f48d47885..bf49c6891c7faa6646f1bd7933e4dcb5aedabff6 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -7361,6 +7361,7 @@ class LUInstanceReboot(LogicalUnit):
     instance = self.instance
     ignore_secondaries = self.op.ignore_secondaries
     reboot_type = self.op.reboot_type
+    reason = self.op.reason
 
     remote_info = self.rpc.call_instance_info(instance.primary_node,
                                               instance.name,
@@ -7376,7 +7377,8 @@ class LUInstanceReboot(LogicalUnit):
         self.cfg.SetDiskID(disk, node_current)
       result = self.rpc.call_instance_reboot(node_current, instance,
                                              reboot_type,
-                                             self.op.shutdown_timeout)
+                                             self.op.shutdown_timeout,
+                                             reason)
       result.Raise("Could not reboot instance")
     else:
       if instance_running:
diff --git a/lib/constants.py b/lib/constants.py
index 62813dc26d8e51a8ac5de15e4f74031c7f678631..a767fce9a5b4626976c9cf02c116fba1c901bdac 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -2343,5 +2343,8 @@ INSTANCE_REASON_SOURCES = compat.UniqueFrozenset([
   INSTANCE_REASON_SOURCE_UNKNOWN,
   ])
 
+# The default reasons for the change of state of an instance
+INSTANCE_REASON_REBOOT = "reboot"
+
 # Do not re-export imported modules
 del re, _vcsversion, _autoconf, socket, pathutils, compat
diff --git a/lib/opcodes.py b/lib/opcodes.py
index 3015a5468a1699b1380f5707498a427ad240e107..43f4973827ab8e6053a315f34195edfd085b7168 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -1451,6 +1451,15 @@ class OpInstanceReboot(OpCode):
      "Whether to start the instance even if secondary disks are failing"),
     ("reboot_type", ht.NoDefault, ht.TElemOf(constants.REBOOT_TYPES),
      "How to reboot instance"),
+    ("reason", (constants.INSTANCE_REASON_SOURCE_UNKNOWN, None),
+     ht.TAnd(ht.TOr(ht.TList, ht.TTuple),
+             ht.TIsLength(2),
+             ht.TItems([
+              ht.TElemOf(constants.INSTANCE_REASON_SOURCES),
+              ht.TMaybeString,
+             ])
+             ),
+     "The reason why the reboot is happening"),
     ]
   OP_RESULT = ht.TNone
 
diff --git a/lib/rapi/client.py b/lib/rapi/client.py
index cf7971132300264afe96f5216e0e392626211580..d02faffe530f4e1a10adc876434c75b2ff508351 100644
--- a/lib/rapi/client.py
+++ b/lib/rapi/client.py
@@ -1001,11 +1001,11 @@ class GanetiRapiClient(object): # pylint: disable=R0904
                               (GANETI_RAPI_VERSION, instance)), query, None)
 
   def RebootInstance(self, instance, reboot_type=None, ignore_secondaries=None,
-                     dry_run=False):
+                     dry_run=False, reason_text=None):
     """Reboots an instance.
 
     @type instance: str
-    @param instance: instance to rebot
+    @param instance: instance to reboot
     @type reboot_type: str
     @param reboot_type: one of: hard, soft, full
     @type ignore_secondaries: bool
@@ -1013,6 +1013,8 @@ class GanetiRapiClient(object): # pylint: disable=R0904
         while re-assembling disks (in hard-reboot mode only)
     @type dry_run: bool
     @param dry_run: whether to perform a dry run
+    @type reason_text: string
+    @param reason_text: the reason for the reboot
     @rtype: string
     @return: job id
 
@@ -1022,6 +1024,7 @@ class GanetiRapiClient(object): # pylint: disable=R0904
     _AppendIf(query, reboot_type, ("type", reboot_type))
     _AppendIf(query, ignore_secondaries is not None,
               ("ignore_secondaries", ignore_secondaries))
+    _AppendIf(query, reason_text, ("reason_text", reason_text))
 
     return self._SendRequest(HTTP_POST,
                              ("/%s/instances/%s/reboot" %
diff --git a/lib/rapi/rlib2.py b/lib/rapi/rlib2.py
index 4e07d34d24e7436f992b5c631a94dbda53b2226b..89a99c5ce7f8ab4e95a6bd2307b00d9d9290296b 100644
--- a/lib/rapi/rlib2.py
+++ b/lib/rapi/rlib2.py
@@ -1040,6 +1040,11 @@ class R_2_instances_name_reboot(baserlib.OpcodeResource):
         self.queryargs.get("type", [constants.INSTANCE_REBOOT_HARD])[0],
       "ignore_secondaries": bool(self._checkIntVariable("ignore_secondaries")),
       "dry_run": self.dryRun(),
+      "reason": (
+        constants.INSTANCE_REASON_SOURCE_RAPI,
+        self._checkStringVariable("reason_text",
+                                  default=constants.INSTANCE_REASON_REBOOT),
+      )
       })
 
 
diff --git a/lib/rpc_defs.py b/lib/rpc_defs.py
index f5f1c34b23f50452bca6f6a31934f778ca55ceb1..a9ed9dad13c36791d0552610101066c897dad1b3 100644
--- a/lib/rpc_defs.py
+++ b/lib/rpc_defs.py
@@ -230,6 +230,7 @@ _INSTANCE_CALLS = [
     ("inst", ED_INST_DICT, "Instance object"),
     ("reboot_type", None, None),
     ("shutdown_timeout", None, None),
+    ("reason_text", None, "Reason for the reboot"),
     ], None, None, "Returns the list of running instances on the given nodes"),
   ("instance_shutdown", SINGLE, None, constants.RPC_TMO_NORMAL, [
     ("instance", ED_INST_DICT, "Instance object"),
diff --git a/lib/server/noded.py b/lib/server/noded.py
index 14b7997cb4dd2dddf0ac82301b39e165070a65f5..aa9243f8e1bb8de69362cde5619893a1d688b33d 100644
--- a/lib/server/noded.py
+++ b/lib/server/noded.py
@@ -112,6 +112,21 @@ def _DecodeImportExportIO(ieio, ieioargs):
   return ieioargs
 
 
+def _DefaultAlternative(value, default):
+  """Returns the given value, unless it is None. In that case, returns a
+  default alternative.
+
+  @param value: The value to return if it is not None.
+  @param default: The value to return as a default alternative.
+  @return: The given value or the default alternative.\
+
+  """
+  if value:
+    return value
+
+  return default
+
+
 class MlockallRequestExecutor(http.server.HttpServerRequestExecutor):
   """Subclass ensuring request handlers are locked in RAM.
 
@@ -633,7 +648,12 @@ class NodeRequestHandler(http.server.HttpServerHandler):
     instance = objects.Instance.FromDict(params[0])
     reboot_type = params[1]
     shutdown_timeout = params[2]
-    return backend.InstanceReboot(instance, reboot_type, shutdown_timeout)
+    (reason_source, reason_text) = params[3]
+    reason_text = _DefaultAlternative(reason_text,
+                                      constants.INSTANCE_REASON_REBOOT)
+    reason = backend.InstReason(reason_source, reason_text)
+    return backend.InstanceReboot(instance, reboot_type, shutdown_timeout,
+                                  reason)
 
   @staticmethod
   def perspective_instance_balloon_memory(params):
diff --git a/src/Ganeti/OpCodes.hs b/src/Ganeti/OpCodes.hs
index 66d6e793e9ba0301e573f72f9b04a439b5510312..f720577633dfe238aed6404731184228c36143e5 100644
--- a/src/Ganeti/OpCodes.hs
+++ b/src/Ganeti/OpCodes.hs
@@ -344,6 +344,7 @@ $(genOpCode "OpCode"
      , pShutdownTimeout
      , pIgnoreSecondaries
      , pRebootType
+     , pReason
      ])
   , ("OpInstanceMove",
      [ pInstanceName
diff --git a/test/hs/Test/Ganeti/OpCodes.hs b/test/hs/Test/Ganeti/OpCodes.hs
index 4dc39ae7a069620dba8c6aaca4ccf9b933a38456..4c06ee2dfb128283bb1d8f63714eaf011b72a1c4 100644
--- a/test/hs/Test/Ganeti/OpCodes.hs
+++ b/test/hs/Test/Ganeti/OpCodes.hs
@@ -241,7 +241,7 @@ instance Arbitrary OpCodes.OpCode where
           arbitrary <*> arbitrary
       "OP_INSTANCE_REBOOT" ->
         OpCodes.OpInstanceReboot <$> genFQDN <*> arbitrary <*>
-          arbitrary <*> arbitrary
+          arbitrary <*> arbitrary <*> ((,) <$> arbitrary <*> genStringNE)
       "OP_INSTANCE_MOVE" ->
         OpCodes.OpInstanceMove <$> genFQDN <*> arbitrary <*> arbitrary <*>
           genNodeNameNE <*> arbitrary
@@ -397,6 +397,10 @@ genMacPrefix = do
   octets <- vectorOf 3 $ choose (0::Int, 255)
   mkNonEmpty . intercalate ":" $ map (printf "%02x") octets
 
+-- | Generate a non empty string
+genStringNE :: Gen NonEmptyString
+genStringNE = genName >>= mkNonEmpty
+
 -- | Arbitrary instance for MetaOpCode, defined here due to TH ordering.
 $(genArbitrary ''OpCodes.MetaOpCode)
 
diff --git a/test/py/ganeti.rapi.client_unittest.py b/test/py/ganeti.rapi.client_unittest.py
index d9820c25f0c00aab8cbae0dc23b131eb47c129a4..e78a1d9b6ae104d97f2af5ca0de3f06dca04dc28 100755
--- a/test/py/ganeti.rapi.client_unittest.py
+++ b/test/py/ganeti.rapi.client_unittest.py
@@ -592,6 +592,19 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertQuery("tag", ["awesome"])
 
   def testRebootInstance(self):
+    self.rapi.AddResponse("6146")
+    job_id = self.client.RebootInstance("i-bar", reboot_type="hard",
+                                        ignore_secondaries=True, dry_run=True,
+                                        reason_text="Updates")
+    self.assertEqual(6146, job_id)
+    self.assertHandler(rlib2.R_2_instances_name_reboot)
+    self.assertItems(["i-bar"])
+    self.assertDryRun()
+    self.assertQuery("type", ["hard"])
+    self.assertQuery("ignore_secondaries", ["1"])
+    self.assertQuery("reason_text", ["Updates"])
+
+  def testRebootInstanceDefaultReason(self):
     self.rapi.AddResponse("6146")
     job_id = self.client.RebootInstance("i-bar", reboot_type="hard",
                                         ignore_secondaries=True, dry_run=True)
@@ -601,6 +614,7 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertDryRun()
     self.assertQuery("type", ["hard"])
     self.assertQuery("ignore_secondaries", ["1"])
+    self.assertQuery("reason_text", None)
 
   def testShutdownInstance(self):
     self.rapi.AddResponse("1487")
diff --git a/test/py/ganeti.rapi.rlib2_unittest.py b/test/py/ganeti.rapi.rlib2_unittest.py
index 0f2c735e3abe3fb5916df44b6006285a5bf80e4c..b66d01a4cab3220a16bef7a4a4d7e21ea37af602 100755
--- a/test/py/ganeti.rapi.rlib2_unittest.py
+++ b/test/py/ganeti.rapi.rlib2_unittest.py
@@ -370,6 +370,7 @@ class TestInstanceReboot(unittest.TestCase):
     handler = _CreateHandler(rlib2.R_2_instances_name_reboot, ["inst847"], {
       "dry-run": ["1"],
       "ignore_secondaries": ["1"],
+      "reason_text": ["System update"]
       }, {}, clfactory)
     job_id = handler.POST()
 
@@ -383,6 +384,10 @@ class TestInstanceReboot(unittest.TestCase):
     self.assertEqual(op.reboot_type, constants.INSTANCE_REBOOT_HARD)
     self.assertTrue(op.ignore_secondaries)
     self.assertTrue(op.dry_run)
+    self.assertEqual(op.reason,
+      (constants.INSTANCE_REASON_SOURCE_RAPI,
+       "System update",
+      ))
 
     self.assertRaises(IndexError, cl.GetNextSubmittedJob)