Commit 310fbb64 authored by Iustin Pop's avatar Iustin Pop
Browse files

DRBD: ignore unreadable meta devices



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.
Signed-off-by: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parent 313b2dd4
...@@ -34,6 +34,10 @@ from ganeti import constants ...@@ -34,6 +34,10 @@ from ganeti import constants
from ganeti import objects from ganeti import objects
# Size of reads in _CanReadDevice
_DEVICE_READ_SIZE = 128 * 1024
def _IgnoreError(fn, *args, **kwargs): def _IgnoreError(fn, *args, **kwargs):
"""Executes the given function, ignoring BlockDeviceErrors. """Executes the given function, ignoring BlockDeviceErrors.
...@@ -66,6 +70,20 @@ def _ThrowError(msg, *args): ...@@ -66,6 +70,20 @@ def _ThrowError(msg, *args):
raise errors.BlockDeviceError(msg) 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:
utils.ReadFile(path, size=_DEVICE_READ_SIZE)
return True
except EnvironmentError, err:
logging.warning("Can't read from device %s", path, exc_info=True)
return False
class BlockDev(object): class BlockDev(object):
"""Block device abstract class. """Block device abstract class.
...@@ -960,6 +978,17 @@ class DRBD8(BaseDRBD): ...@@ -960,6 +978,17 @@ class DRBD8(BaseDRBD):
def __init__(self, unique_id, children, size): def __init__(self, unique_id, children, size):
if children and children.count(None) > 0: if children and children.count(None) > 0:
children = [] 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) super(DRBD8, self).__init__(unique_id, children, size)
self.major = self._DRBD_MAJOR self.major = self._DRBD_MAJOR
version = self._GetVersion() version = self._GetVersion()
...@@ -968,13 +997,6 @@ class DRBD8(BaseDRBD): ...@@ -968,13 +997,6 @@ class DRBD8(BaseDRBD):
" usage: kernel is %s.%s, ganeti wants 8.x", " usage: kernel is %s.%s, ganeti wants 8.x",
version['k_major'], version['k_minor']) 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 if (self._lhost is not None and self._lhost == self._rhost and
self._lport == self._rport): self._lport == self._rport):
raise ValueError("Invalid configuration data, same local/remote %s" % raise ValueError("Invalid configuration data, same local/remote %s" %
......
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