From 82c54b5b9aa07dcfb41bdf25504dfd8e3a517e0e Mon Sep 17 00:00:00 2001
From: Michael Hanselmann <hansmi@google.com>
Date: Fri, 17 Feb 2012 17:49:35 +0100
Subject: [PATCH] =?UTF-8?q?config:=20Add=20check=20for=20disk's=20?=
 =?UTF-8?q?=E2=80=9Civ=5Fname=E2=80=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This check verifies β€œiv_name” of all instance disks. If one is wrong
(which shouldn't happen in the first place), cluster verification will
warn:

β€œERROR: cluster: Instance 'inst.example.com' has wrongly named disks:
name of disk 1 should be 'disk/1', but is 'disk/4'”

Signed-off-by: Michael Hanselmann <hansmi@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>
Reviewed-by: RenΓ© Nussbaumer <rn@google.com>
---
 lib/config.py                  | 29 +++++++++++++++++++++++++++++
 test/ganeti.config_unittest.py | 24 ++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/lib/config.py b/lib/config.py
index 8c5fda9cb..97b3939ee 100644
--- a/lib/config.py
+++ b/lib/config.py
@@ -133,6 +133,26 @@ def _MatchNameComponentIgnoreCase(short_name, names):
   return utils.MatchNameComponent(short_name, names, case_sensitive=False)
 
 
+def _CheckInstanceDiskIvNames(disks):
+  """Checks if instance's disks' C{iv_name} attributes are in order.
+
+  @type disks: list of L{objects.Disk}
+  @param disks: List of disks
+  @rtype: list of tuples; (int, string, string)
+  @return: List of wrongly named disks, each tuple contains disk index,
+    expected and actual name
+
+  """
+  result = []
+
+  for (idx, disk) in enumerate(disks):
+    exp_iv_name = "disk/%s" % idx
+    if disk.iv_name != exp_iv_name:
+      result.append((idx, exp_iv_name, disk.iv_name))
+
+  return result
+
+
 class ConfigWriter:
   """The interface to the cluster configuration.
 
@@ -510,6 +530,15 @@ class ConfigWriter:
                        (instance.name, idx, msg) for msg in disk.Verify()])
         result.extend(self._CheckDiskIDs(disk, seen_lids, seen_pids))
 
+      wrong_names = _CheckInstanceDiskIvNames(instance.disks)
+      if wrong_names:
+        tmp = "; ".join(("name of disk %s should be '%s', but is '%s'" %
+                         (idx, exp_name, actual_name))
+                        for (idx, exp_name, actual_name) in wrong_names)
+
+        result.append("Instance '%s' has wrongly named disks: %s" %
+                      (instance.name, tmp))
+
     # cluster-wide pool of free ports
     for free_port in cluster.tcpudp_port_pool:
       if free_port not in ports:
diff --git a/test/ganeti.config_unittest.py b/test/ganeti.config_unittest.py
index e82872c6b..9a3e27bcc 100755
--- a/test/ganeti.config_unittest.py
+++ b/test/ganeti.config_unittest.py
@@ -39,6 +39,7 @@ from ganeti import objects
 from ganeti import utils
 from ganeti import netutils
 from ganeti import compat
+from ganeti import cmdlib
 
 from ganeti.config import TemporaryReservationManager
 
@@ -382,5 +383,28 @@ class TestTRM(unittest.TestCase):
     self.assertFalse(t.Reserved("a"))
 
 
+class TestCheckInstanceDiskIvNames(unittest.TestCase):
+  @staticmethod
+  def _MakeDisks(names):
+    return [objects.Disk(iv_name=name) for name in names]
+
+  def testNoError(self):
+    disks = self._MakeDisks(["disk/0", "disk/1"])
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
+    cmdlib._UpdateIvNames(0, disks)
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
+
+  def testWrongNames(self):
+    disks = self._MakeDisks(["disk/1", "disk/3", "disk/2"])
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [
+      (0, "disk/0", "disk/1"),
+      (1, "disk/1", "disk/3"),
+      ])
+
+    # Fix names
+    cmdlib._UpdateIvNames(0, disks)
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
+
+
 if __name__ == '__main__':
   testutils.GanetiTestProgram()
-- 
GitLab