From 767d52d30df44d15f76b5aefc6e1e4f70f21f39b Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Tue, 20 Jan 2009 11:18:31 +0000 Subject: [PATCH] DRBD: check for in-use minor during Create In order to prevent errors with old, in-use DRBD minors, we check and abort at create time if our minor is already in use. For this we need to also modify DRBD8Status to be able to parse cs:Unconfigured devices. Reviewed-by: ultrotter --- lib/bdev.py | 38 +++++++++++++++++++++++++++--------- test/ganeti.bdev_unittest.py | 10 ++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/lib/bdev.py b/lib/bdev.py index f1ade2eaa..9207e2c06 100644 --- a/lib/bdev.py +++ b/lib/bdev.py @@ -540,20 +540,28 @@ class DRBD8Status(object): Note that this doesn't support unconfigured devices (cs:Unconfigured). """ + UNCONF_RE = re.compile(r"\s*[0-9]+:\s*cs:Unconfigured$") LINE_RE = re.compile(r"\s*[0-9]+:\s*cs:(\S+)\s+st:([^/]+)/(\S+)" "\s+ds:([^/]+)/(\S+)\s+.*$") SYNC_RE = re.compile(r"^.*\ssync'ed:\s*([0-9.]+)%.*" "\sfinish: ([0-9]+):([0-9]+):([0-9]+)\s.*$") def __init__(self, procline): - m = self.LINE_RE.match(procline) - if not m: - raise errors.BlockDeviceError("Can't parse input data '%s'" % procline) - self.cstatus = m.group(1) - self.lrole = m.group(2) - self.rrole = m.group(3) - self.ldisk = m.group(4) - self.rdisk = m.group(5) + u = self.UNCONF_RE.match(procline) + if u: + self.cstatus = "Unconfigured" + self.lrole = self.rrole = self.ldisk = self.rdisk = None + else: + m = self.LINE_RE.match(procline) + if not m: + raise errors.BlockDeviceError("Can't parse input data '%s'" % procline) + self.cstatus = m.group(1) + self.lrole = m.group(2) + self.rrole = m.group(3) + self.ldisk = m.group(4) + self.rdisk = m.group(5) + + # end reading of data from the LINE_RE or UNCONF_RE self.is_standalone = self.cstatus == "StandAlone" self.is_wfconn = self.cstatus == "WFConnection" @@ -568,7 +576,8 @@ class DRBD8Status(object): self.is_diskless = self.ldisk == "Diskless" self.is_disk_uptodate = self.ldisk == "UpToDate" - self.is_in_resync = self.cstatus in ('SyncSource', 'SyncTarget') + self.is_in_resync = self.cstatus in ("SyncSource", "SyncTarget") + self.is_in_use = self.cstatus != "Unconfigured" m = self.SYNC_RE.match(procline) if m: @@ -1525,6 +1534,17 @@ class DRBD8(BaseDRBD): """ if len(children) != 2: raise errors.ProgrammerError("Invalid setup for the drbd device") + # check that the minor is unused + aminor = unique_id[4] + proc_info = cls._MassageProcData(cls._GetProcData()) + if aminor in proc_info: + status = DRBD8Status(proc_info[aminor]) + in_use = status.is_in_use + else: + in_use = False + if in_use: + raise errors.BlockDeviceError("DRBD minor %d already in use at" + " Create() time" % aminor) meta = children[1] meta.Assemble() if not meta.Attach(): diff --git a/test/ganeti.bdev_unittest.py b/test/ganeti.bdev_unittest.py index 04823eb62..6b7176895 100755 --- a/test/ganeti.bdev_unittest.py +++ b/test/ganeti.bdev_unittest.py @@ -117,18 +117,26 @@ class TestDRBD8Status(testutils.GanetiTestCase): def testMinor0(self): """Test connected, primary device""" stats = bdev.DRBD8Status(self.mass_data[0]) + self.failUnless(stats.is_in_use) self.failUnless(stats.is_connected and stats.is_primary and stats.peer_secondary and stats.is_disk_uptodate) def testMinor1(self): """Test connected, secondary device""" stats = bdev.DRBD8Status(self.mass_data[1]) + self.failUnless(stats.is_in_use) self.failUnless(stats.is_connected and stats.is_secondary and stats.peer_primary and stats.is_disk_uptodate) + def testMinor2(self): + """Test unconfigured device""" + stats = bdev.DRBD8Status(self.mass_data[2]) + self.failIf(stats.is_in_use) + def testMinor4(self): """Test WFconn device""" stats = bdev.DRBD8Status(self.mass_data[4]) + self.failUnless(stats.is_in_use) self.failUnless(stats.is_wfconn and stats.is_primary and stats.rrole == 'Unknown' and stats.is_disk_uptodate) @@ -136,12 +144,14 @@ class TestDRBD8Status(testutils.GanetiTestCase): def testMinor6(self): """Test diskless device""" stats = bdev.DRBD8Status(self.mass_data[6]) + self.failUnless(stats.is_in_use) self.failUnless(stats.is_connected and stats.is_secondary and stats.peer_primary and stats.is_diskless) def testMinor8(self): """Test standalone device""" stats = bdev.DRBD8Status(self.mass_data[8]) + self.failUnless(stats.is_in_use) self.failUnless(stats.is_standalone and stats.rrole == 'Unknown' and stats.is_disk_uptodate) -- GitLab