diff --git a/Makefile.am b/Makefile.am index 444b53e26df45e6778066ca09ca0f539a527277a..3f67337ab93b4ec1f9a9960b9379f532e7073310 100644 --- a/Makefile.am +++ b/Makefile.am @@ -631,6 +631,8 @@ TEST_FILES = \ test/data/proc_drbd8.txt \ test/data/proc_drbd80-emptyline.txt \ test/data/proc_drbd83.txt \ + test/data/proc_drbd83_sync.txt \ + test/data/proc_drbd83_sync_krnl2.6.39.txt \ test/data/sys_drbd_usermode_helper.txt \ test/import-export_unittest-helper diff --git a/NEWS b/NEWS index a6689a3ef173d835028c499f5f240bcd4eeb1a56..9c6a1e398290ac5a2da6072400d0bb5b4a18b94f 100644 --- a/NEWS +++ b/NEWS @@ -136,6 +136,18 @@ Version 2.5.0 beta1 This was the first beta release of the 2.5 series. +Version 2.4.4 +------------- + +*(Released Tue, 23 Aug 2011)* + +Small bug-fixes: + +- Fixed documentation for importing with ``--src-dir`` option +- Fixed a bug in ``ensure-dirs`` with queue/archive permissions +- Fixed a parsing issue with DRBD 8.3.11 in the Linux kernel + + Version 2.4.3 ------------- @@ -167,7 +179,7 @@ Many bug-fixes and a few small features: - Fixed off-by-one bug in job serial generation - ``gnt-node volumes``: Fix instance names - Fixed aliases in bash completion -- Fixed a bug in reopening log files after beeing sent a SIGHUP +- Fixed a bug in reopening log files after being sent a SIGHUP - Added a flag to burnin to allow specifying VCPU count - Bugfixes to non-root Ganeti configuration diff --git a/doc/admin.rst b/doc/admin.rst index b366def1026000222299ec2fe4812113ac21ae8b..665c0e638ccbe82fc4432c5f55c20ab2ec23a568 100644 --- a/doc/admin.rst +++ b/doc/admin.rst @@ -391,16 +391,16 @@ parameters as such: - ``root_path`` to a valid setting (e.g. ``/dev/xvda1``) - ``bootloader_path`` and ``bootloader_args`` to empty -Alternatively, you can delete the kernel management to instances, and +Alternatively, you can delegate the kernel management to instances, and use either ``pvgrub`` or the deprecated ``pygrub``. For this, you must -install the kernels and initrds in the instance, and create a valid grub +install the kernels and initrds in the instance and create a valid GRUB v1 configuration file. For ``pvgrub`` (new in version 2.4.2), you need to set: - ``kernel_path`` to point to the ``pvgrub`` loader present on the node (e.g. ``/usr/lib/xen/boot/pv-grub-x86_32.gz``) -- ``kernel_args`` to the path to the grub config file, relative to the +- ``kernel_args`` to the path to the GRUB config file, relative to the instance (e.g. ``(hd0,0)/grub/menu.lst``) - ``root_path`` **must** be empty - ``bootloader_path`` and ``bootloader_args`` to empty diff --git a/lib/bdev.py b/lib/bdev.py index 905ad1fc13b7f6490977776a986e6dd5d9ac95e2..604a5b4118170f22256db22353e36c09ba382be4 100644 --- a/lib/bdev.py +++ b/lib/bdev.py @@ -791,7 +791,10 @@ class DRBD8Status(object): LINE_RE = re.compile(r"\s*[0-9]+:\s*cs:(\S+)\s+(?:st|ro):([^/]+)/(\S+)" "\s+ds:([^/]+)/(\S+)\s+.*$") SYNC_RE = re.compile(r"^.*\ssync'ed:\s*([0-9.]+)%.*" - "\sfinish: ([0-9]+):([0-9]+):([0-9]+)\s.*$") + # Due to a bug in drbd in the kernel, introduced in + # commit 4b0715f096 (still unfixed as of 2011-08-22) + "(?:\s|M)" + "finish: ([0-9]+):([0-9]+):([0-9]+)\s.*$") CS_UNCONFIGURED = "Unconfigured" CS_STANDALONE = "StandAlone" diff --git a/lib/utils/text.py b/lib/utils/text.py index a4c2777ecda452f022cd63551be8a89b36f1846d..ab9c427a4ae5a23976f2d464a70cc4a1f4669b99 100644 --- a/lib/utils/text.py +++ b/lib/utils/text.py @@ -381,7 +381,7 @@ def UnescapeAndSplit(text, sep=","): e1 = slist.pop(0) if e1.endswith("\\"): num_b = len(e1) - len(e1.rstrip("\\")) - if num_b % 2 == 1: + if num_b % 2 == 1 and slist: e2 = slist.pop(0) # here the backslashes remain (all), and will be reduced in # the next step diff --git a/test/data/proc_drbd83_sync.txt b/test/data/proc_drbd83_sync.txt new file mode 100644 index 0000000000000000000000000000000000000000..ae94186ccab349653a265a26a79ad25693609db9 Binary files /dev/null and b/test/data/proc_drbd83_sync.txt differ diff --git a/test/data/proc_drbd83_sync_krnl2.6.39.txt b/test/data/proc_drbd83_sync_krnl2.6.39.txt new file mode 100644 index 0000000000000000000000000000000000000000..cf3f541d3c52a7c26bf77657133ac27d15a389fd Binary files /dev/null and b/test/data/proc_drbd83_sync_krnl2.6.39.txt differ diff --git a/test/ganeti.bdev_unittest.py b/test/ganeti.bdev_unittest.py index fa1433ec169ab648a08033c2c22834a50da53c54..6f8e3d40adc1616146f36fedba55cd01daee2abc 100755 --- a/test/ganeti.bdev_unittest.py +++ b/test/ganeti.bdev_unittest.py @@ -166,12 +166,21 @@ class TestDRBD8Status(testutils.GanetiTestCase): proc_data = self._TestDataFilename("proc_drbd8.txt") proc80e_data = self._TestDataFilename("proc_drbd80-emptyline.txt") proc83_data = self._TestDataFilename("proc_drbd83.txt") + proc83_sync_data = self._TestDataFilename("proc_drbd83_sync.txt") + proc83_sync_krnl_data = \ + self._TestDataFilename("proc_drbd83_sync_krnl2.6.39.txt") self.proc_data = bdev.DRBD8._GetProcData(filename=proc_data) self.proc80e_data = bdev.DRBD8._GetProcData(filename=proc80e_data) self.proc83_data = bdev.DRBD8._GetProcData(filename=proc83_data) + self.proc83_sync_data = bdev.DRBD8._GetProcData(filename=proc83_sync_data) + self.proc83_sync_krnl_data = \ + bdev.DRBD8._GetProcData(filename=proc83_sync_krnl_data) self.mass_data = bdev.DRBD8._MassageProcData(self.proc_data) self.mass80e_data = bdev.DRBD8._MassageProcData(self.proc80e_data) self.mass83_data = bdev.DRBD8._MassageProcData(self.proc83_data) + self.mass83_sync_data = bdev.DRBD8._MassageProcData(self.proc83_sync_data) + self.mass83_sync_krnl_data = \ + bdev.DRBD8._MassageProcData(self.proc83_sync_krnl_data) def testIOErrors(self): """Test handling of errors while reading the proc file.""" @@ -251,5 +260,15 @@ class TestDRBD8Status(testutils.GanetiTestCase): stats.rrole == 'Unknown' and stats.is_disk_uptodate) + def testDRBD83SyncFine(self): + stats = bdev.DRBD8Status(self.mass83_sync_data[3]) + self.failUnless(stats.is_in_resync) + self.failUnless(stats.sync_percent is not None) + + def testDRBD83SyncBroken(self): + stats = bdev.DRBD8Status(self.mass83_sync_krnl_data[3]) + self.failUnless(stats.is_in_resync) + self.failUnless(stats.sync_percent is not None) + if __name__ == '__main__': testutils.GanetiTestProgram() diff --git a/test/ganeti.utils.text_unittest.py b/test/ganeti.utils.text_unittest.py index 5181db4d36aa963d1f552d59650039d186d0a696..91039e173a765a1bbb6eddc09edda95b4d651d7c 100755 --- a/test/ganeti.utils.text_unittest.py +++ b/test/ganeti.utils.text_unittest.py @@ -350,7 +350,7 @@ class TestUnescapeAndSplit(unittest.TestCase): def setUp(self): # testing more that one separator for regexp safety - self._seps = [",", "+", "."] + self._seps = [",", "+", ".", ":"] def testSimple(self): a = ["a", "b", "c", "d"] @@ -375,6 +375,18 @@ class TestUnescapeAndSplit(unittest.TestCase): b = ["a", "b\\" + sep + "c", "d"] self.failUnlessEqual(utils.UnescapeAndSplit(sep.join(a), sep=sep), b) + def testEscapeAtEnd(self): + for sep in self._seps: + self.assertEqual(utils.UnescapeAndSplit("\\", sep=sep), ["\\"]) + + a = ["a", "b\\", "c"] + b = ["a", "b" + sep + "c\\"] + self.assertEqual(utils.UnescapeAndSplit("%s\\" % sep.join(a), sep=sep), b) + + a = ["\\" + sep, "\\" + sep, "c", "d\\.moo"] + b = [sep, sep, "c", "d.moo\\"] + self.assertEqual(utils.UnescapeAndSplit("%s\\" % sep.join(a), sep=sep), b) + class TestCommaJoin(unittest.TestCase): def test(self):