From fcee765d8c03c093de73760fa464756d7dd358da Mon Sep 17 00:00:00 2001
From: Manuel Franceschini <livewire@google.com>
Date: Thu, 5 Aug 2010 14:56:12 +0200
Subject: [PATCH] Fix bug in bdev when drbd version format is x.x.x.x

This patch fixes a bug reported in [0]. Newer drbd versions can have
another digit beyond the regular major, minor and point release digits.
We modify the regex used to match that with an optional parts which is
not saved.

Furthermore it adds unittests that test for these different cases. Now
the data read from /proc is passed into the _GetVersion method, which
makes testing easier.

[0] http://code.google.com/p/ganeti/issues/detail?id=110

Signed-off-by: Manuel Franceschini <livewire@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>
---
 lib/bdev.py                  | 11 +++++-----
 test/ganeti.bdev_unittest.py | 39 +++++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/lib/bdev.py b/lib/bdev.py
index 3de9c27ea..19c991fe6 100644
--- a/lib/bdev.py
+++ b/lib/bdev.py
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007 Google Inc.
+# Copyright (C) 2006, 2007, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -815,7 +815,7 @@ class BaseDRBD(BlockDev): # pylint: disable-msg=W0223
   0.7 and 8.x versions of DRBD.
 
   """
-  _VERSION_RE = re.compile(r"^version: (\d+)\.(\d+)\.(\d+)"
+  _VERSION_RE = re.compile(r"^version: (\d+)\.(\d+)\.(\d+)(?:\.\d+)?"
                            r" \(api:(\d+)/proto:(\d+)(?:-(\d+))?\)")
   _VALID_LINE_RE = re.compile("^ *([0-9]+): cs:([^ ]+).*$")
   _UNUSED_LINE_RE = re.compile("^ *([0-9]+): cs:Unconfigured$")
@@ -873,7 +873,7 @@ class BaseDRBD(BlockDev): # pylint: disable-msg=W0223
     return results
 
   @classmethod
-  def _GetVersion(cls):
+  def _GetVersion(cls, proc_data):
     """Return the DRBD version.
 
     This will return a dict with keys:
@@ -885,7 +885,6 @@ class BaseDRBD(BlockDev): # pylint: disable-msg=W0223
       - proto2 (only on drbd > 8.2.X)
 
     """
-    proc_data = cls._GetProcData()
     first_line = proc_data[0].strip()
     version = cls._VERSION_RE.match(first_line)
     if not version:
@@ -1034,7 +1033,7 @@ class DRBD8(BaseDRBD):
         children = []
     super(DRBD8, self).__init__(unique_id, children, size)
     self.major = self._DRBD_MAJOR
-    version = self._GetVersion()
+    version = self._GetVersion(self._GetProcData())
     if version['k_major'] != 8 :
       _ThrowError("Mismatch in DRBD kernel version and requested ganeti"
                   " usage: kernel is %s.%s, ganeti wants 8.x",
@@ -1260,7 +1259,7 @@ class DRBD8(BaseDRBD):
     if size:
       args.extend(["-d", "%sm" % size])
     if not constants.DRBD_BARRIERS: # disable barriers, if configured so
-      version = cls._GetVersion()
+      version = cls._GetVersion(cls._GetProcData())
       # various DRBD versions support different disk barrier options;
       # what we aim here is to revert back to the 'drain' method of
       # disk flushes and to disable metadata barriers, in effect going
diff --git a/test/ganeti.bdev_unittest.py b/test/ganeti.bdev_unittest.py
index a2ce0977e..fa1433ec1 100755
--- a/test/ganeti.bdev_unittest.py
+++ b/test/ganeti.bdev_unittest.py
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2006, 2007 Google Inc.
+# Copyright (C) 2006, 2007, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -31,6 +31,43 @@ from ganeti import errors
 import testutils
 
 
+class TestBaseDRBD(testutils.GanetiTestCase):
+  def testGetVersion(self):
+    data = [
+      ["version: 8.0.12 (api:76/proto:86-91)"],
+      ["version: 8.2.7 (api:88/proto:0-100)"],
+      ["version: 8.3.7.49 (api:188/proto:13-191)"],
+    ]
+    result = [
+      {
+      "k_major": 8,
+      "k_minor": 0,
+      "k_point": 12,
+      "api": 76,
+      "proto": 86,
+      "proto2": "91",
+      },
+      {
+      "k_major": 8,
+      "k_minor": 2,
+      "k_point": 7,
+      "api": 88,
+      "proto": 0,
+      "proto2": "100",
+      },
+      {
+      "k_major": 8,
+      "k_minor": 3,
+      "k_point": 7,
+      "api": 188,
+      "proto": 13,
+      "proto2": "191",
+      }
+    ]
+    for d,r in zip(data, result):
+      self.assertEqual(bdev.BaseDRBD._GetVersion(d), r)
+
+
 class TestDRBD8Runner(testutils.GanetiTestCase):
   """Testing case for DRBD8"""
 
-- 
GitLab