diff --git a/lib/bdev.py b/lib/bdev.py index f1ade2eaa0c9bbbe87328de4cc589949626d3d1c..9207e2c06762223e8f2b9fd4bf3b97e08ea1b916 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 04823eb62fe9351b1065f101593d94f577a0cae5..6b71768959a6ae5fc64567c93e3f094b903a3219 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)