Commit 767d52d3 authored by Iustin Pop's avatar Iustin Pop

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
parent f65f63ef
......@@ -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():
......
......@@ -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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment