Reason trail implementation for instance reboot
authorMichele Tartara <mtartara@google.com>
Fri, 22 Mar 2013 18:31:56 +0000 (19:31 +0100)
committerMichele Tartara <mtartara@google.com>
Mon, 22 Apr 2013 11:19:35 +0000 (11:19 +0000)
This commits allows ganeti to correctly forward the reason trail information
regarding instance reboot.

Signed-off-by: Michele Tartara <mtartara@google.com>
Reviewed-by: Helga Velroyen <helgav@google.com>

lib/backend.py
lib/cmdlib.py
lib/rapi/client.py
lib/rpc_defs.py
lib/server/noded.py
test/py/ganeti.rapi.client_unittest.py
test/py/ganeti.rapi.rlib2_unittest.py

index abe6b39..7d8315d 100644 (file)
@@ -1424,7 +1424,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}
@@ -1442,6 +1442,8 @@ def InstanceReboot(instance, reboot_type, shutdown_timeout):
         instance (instead of a call_instance_reboot RPC)
   @type shutdown_timeout: integer
   @param shutdown_timeout: maximum timeout for soft shutdown
+  @type reason: list of reasons
+  @param reason: the reason trail for this reboot
   @rtype: None
 
   """
@@ -1460,6 +1462,7 @@ def InstanceReboot(instance, reboot_type, shutdown_timeout):
     try:
       InstanceShutdown(instance, shutdown_timeout)
       result = StartInstance(instance, False)
+      _StoreInstReasonTrail(instance.name, reason)
       return result
     except errors.HypervisorError, err:
       _Fail("Failed to hard reboot instance %s: %s", instance.name, err)
index 2c6d216..d6f16d0 100644 (file)
@@ -7440,6 +7440,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,
@@ -7455,7 +7456,7 @@ 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:
index 5fc576f..ace4d1e 100644 (file)
@@ -1001,7 +1001,7 @@ 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=None):
     """Reboots an instance.
 
     @type instance: str
@@ -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: string
+    @param reason: 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, ("reason", reason))
 
     return self._SendRequest(HTTP_POST,
                              ("/%s/instances/%s/reboot" %
index f5f1c34..bf3cbe8 100644 (file)
@@ -230,6 +230,7 @@ _INSTANCE_CALLS = [
     ("inst", ED_INST_DICT, "Instance object"),
     ("reboot_type", None, None),
     ("shutdown_timeout", None, None),
+    ("reason", None, "The 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"),
index 2e1ceaa..c81352b 100644 (file)
@@ -660,7 +660,10 @@ 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)
+    trail = params[3]
+    _extendReasonTrail(trail, "reboot")
+    return backend.InstanceReboot(instance, reboot_type, shutdown_timeout,
+                                  trail)
 
   @staticmethod
   def perspective_instance_balloon_memory(params):
index ab518e5..3174c69 100755 (executable)
@@ -594,13 +594,15 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
   def testRebootInstance(self):
     self.rapi.AddResponse("6146")
     job_id = self.client.RebootInstance("i-bar", reboot_type="hard",
-                                        ignore_secondaries=True, dry_run=True)
+                                        ignore_secondaries=True, dry_run=True,
+                                        reason="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", ["Updates"])
 
   def testRebootInstanceDefaultReason(self):
     self.rapi.AddResponse("6146")
@@ -612,6 +614,7 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertDryRun()
     self.assertQuery("type", ["hard"])
     self.assertQuery("ignore_secondaries", ["1"])
+    self.assertQuery("reason", None)
 
   def testShutdownInstance(self):
     self.rapi.AddResponse("1487")
index d4d3602..e19c925 100755 (executable)
@@ -370,6 +370,7 @@ class TestInstanceReboot(unittest.TestCase):
     handler = _CreateHandler(rlib2.R_2_instances_name_reboot, ["inst847"], {
       "dry-run": ["1"],
       "ignore_secondaries": ["1"],
+      "reason": ["System update"],
       }, {}, clfactory)
     job_id = handler.POST()
 
@@ -383,6 +384,12 @@ 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[0][0], constants.OPCODE_REASON_SRC_USER)
+    self.assertEqual(op.reason[0][1], "System update")
+    self.assertEqual(op.reason[1][0],
+                     "%s:%s" % (constants.OPCODE_REASON_SRC_RLIB2,
+                                "instances_name_reboot"))
+    self.assertEqual(op.reason[1][1], "")
 
     self.assertRaises(IndexError, cl.GetNextSubmittedJob)