The DRBD driver can ignore dead disks but not dead meta devices (for
which it refuses to configure the minor). To handle this case, we check
that the meta device is readable and if not we ignore it (the same as
when backend._RecursiveAssembleBD didn't find it).
A needed change is the move of some checks and initialisers before this
test (which is before the super().__init__ call), but that should be
fine.
[To be removed from commit msg: Alternative implementation would be to
not read from the device but checks that it returns LDS_OKAY on
GetSyncStatus.ldisk_status, but that doesn't necessarily tell if we can
read from it]
---
lib/bdev.py | 36 +++++++++++++++++++++++++++++-------
1 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/lib/bdev.py b/lib/bdev.py
index 7991345..09b5b14 100644
--- a/lib/bdev.py
+++ b/lib/bdev.py
@@ -66,6 +66,24 @@ def _ThrowError(msg, *args):
raise errors.BlockDeviceError(msg)
+def _CanReadDevice(path):
+ """Check if we can read from the given device.
+
+ This tries to read the first 128k of the device.
+
+ """
+ try:
+ f = open(path, "r")
+ try:
+ f.read(128*1024)
+ finally:
+ f.close()
+ return True
+ except EnvironmentError, err:
+ logging.warning("Can't read from device %s", path, exc_info=True)
+ return False
+
+
class BlockDev(object):
"""Block device abstract class.
@@ -960,6 +978,17 @@ class DRBD8(BaseDRBD):
def __init__(self, unique_id, children, size):
if children and children.count(None) > 0:
children = []
+ if len(children) not in (0, 2):
+ raise ValueError("Invalid configuration data %s" % str(children))
+ if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 6:
+ raise ValueError("Invalid configuration data %s" % str(unique_id))
+ (self._lhost, self._lport,
+ self._rhost, self._rport,
+ self._aminor, self._secret) = unique_id
+ if children:
+ if not _CanReadDevice(children[1].dev_path):
+ logging.info("drbd%s: Ignoring unreadable meta device", self._aminor)
+ children = []
super(DRBD8, self).__init__(unique_id, children, size)
self.major = self._DRBD_MAJOR
version = self._GetVersion()
@@ -968,13 +997,6 @@ class DRBD8(BaseDRBD):
" usage: kernel is %s.%s, ganeti wants 8.x",
version['k_major'], version['k_minor'])
- if len(children) not in (0, 2):
- raise ValueError("Invalid configuration data %s" % str(children))
- if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 6:
- raise ValueError("Invalid configuration data %s" % str(unique_id))
- (self._lhost, self._lport,
- self._rhost, self._rport,
- self._aminor, self._secret) = unique_id
if (self._lhost is not None and self._lhost == self._rhost and
self._lport == self._rport):
raise ValueError("Invalid configuration data, same local/remote %s" %
--
1.6.5.3