import errno
import pyparsing as pyp
import os
+import logging
from ganeti import utils
-from ganeti import logger
from ganeti import errors
from ganeti import constants
self.unique_id = unique_id
self.major = None
self.minor = None
+ self.attached = False
def Assemble(self):
"""Assemble the device from its components.
raise ValueError("Invalid configuration data %s" % str(unique_id))
self._vg_name, self._lv_name = unique_id
self.dev_path = "/dev/%s/%s" % (self._vg_name, self._lv_name)
+ self._degraded = True
+ self.major = self.minor = None
self.Attach()
@classmethod
"--separator=:"]
result = utils.RunCmd(command)
if result.failed:
- logger.Error("Can't get the PV information: %s - %s" %
- (result.fail_reason, result.output))
+ logging.error("Can't get the PV information: %s - %s",
+ result.fail_reason, result.output)
return None
data = []
for line in result.stdout.splitlines():
fields = line.strip().split(':')
if len(fields) != 4:
- logger.Error("Can't parse pvs output: line '%s'" % line)
+ logging.error("Can't parse pvs output: line '%s'", line)
return None
# skip over pvs from another vg or ones which are not allocatable
if fields[1] != vg_name or fields[3][0] != 'a':
result = utils.RunCmd(["lvremove", "-f", "%s/%s" %
(self._vg_name, self._lv_name)])
if result.failed:
- logger.Error("Can't lvremove: %s - %s" %
- (result.fail_reason, result.output))
+ logging.error("Can't lvremove: %s - %s",
+ result.fail_reason, result.output)
return not result.failed
recorded.
"""
- result = utils.RunCmd(["lvdisplay", self.dev_path])
+ self.attached = False
+ result = utils.RunCmd(["lvs", "--noheadings", "--separator=,",
+ "-olv_attr,lv_kernel_major,lv_kernel_minor",
+ self.dev_path])
if result.failed:
- logger.Error("Can't find LV %s: %s, %s" %
- (self.dev_path, result.fail_reason, result.output))
+ logging.error("Can't find LV %s: %s, %s",
+ self.dev_path, result.fail_reason, result.output)
+ return False
+ out = result.stdout.strip().rstrip(',')
+ out = out.split(",")
+ if len(out) != 3:
+ logging.error("Can't parse LVS output, len(%s) != 3", str(out))
return False
- match = re.compile("^ *Block device *([0-9]+):([0-9]+).*$")
- for line in result.stdout.splitlines():
- match_result = match.match(line)
- if match_result:
- self.major = int(match_result.group(1))
- self.minor = int(match_result.group(2))
- return True
- return False
+
+ status, major, minor = out[:3]
+ if len(status) != 6:
+ logging.error("lvs lv_attr is not 6 characters (%s)", status)
+ return False
+
+ try:
+ major = int(major)
+ minor = int(minor)
+ except ValueError, err:
+ logging.error("lvs major/minor cannot be parsed: %s", str(err))
+
+ self.major = major
+ self.minor = minor
+ self._degraded = status[0] == 'v' # virtual volume, i.e. doesn't backing
+ # storage
+ self.attached = True
+ return True
def Assemble(self):
"""Assemble the device.
"""
result = utils.RunCmd(["lvchange", "-ay", self.dev_path])
if result.failed:
- logger.Error("Can't activate lv %s: %s" % (self.dev_path, result.output))
- return not result.failed
+ logging.error("Can't activate lv %s: %s", self.dev_path, result.output)
+ return False
+ return self.Attach()
def Shutdown(self):
"""Shutdown the device.
physical disk failure and subsequent 'vgreduce --removemissing' on
the volume group.
+ The status was already read in Attach, so we just return it.
+
"""
- result = utils.RunCmd(["lvs", "--noheadings", "-olv_attr", self.dev_path])
- if result.failed:
- logger.Error("Can't display lv: %s - %s" %
- (result.fail_reason, result.output))
- return None, None, True, True
- out = result.stdout.strip()
- # format: type/permissions/alloc/fixed_minor/state/open
- if len(out) != 6:
- logger.Debug("Error in lvs output: attrs=%s, len != 6" % out)
- return None, None, True, True
- ldisk = out[0] == 'v' # virtual volume, i.e. doesn't have
- # backing storage
- return None, None, ldisk, ldisk
+ return None, None, self._degraded, self._degraded
def Open(self, force=False):
"""Make the device ready for I/O.
"""
if minor is None:
self.minor = self.dev_path = None
+ self.attached = False
else:
self.minor = minor
self.dev_path = self._DevPath(minor)
+ self.attached = True
@staticmethod
def _CheckMetaSize(meta_device):
"""
result = utils.RunCmd(["blockdev", "--getsize", meta_device])
if result.failed:
- logger.Error("Failed to get device size: %s - %s" %
- (result.fail_reason, result.output))
+ logging.error("Failed to get device size: %s - %s",
+ result.fail_reason, result.output)
return False
try:
sectors = int(result.stdout)
except ValueError:
- logger.Error("Invalid output from blockdev: '%s'" % result.stdout)
+ logging.error("Invalid output from blockdev: '%s'", result.stdout)
return False
bytes = sectors * 512
if bytes < 128 * 1024 * 1024: # less than 128MiB
- logger.Error("Meta device too small (%.2fMib)" % (bytes / 1024 / 1024))
+ logging.error("Meta device too small (%.2fMib)", (bytes / 1024 / 1024))
return False
if bytes > (128 + 32) * 1024 * 1024: # account for an extra (big) PE on LVM
- logger.Error("Meta device too big (%.2fMiB)" % (bytes / 1024 / 1024))
+ logging.error("Meta device too big (%.2fMiB)", (bytes / 1024 / 1024))
return False
return True
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) != 4:
+ 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 = 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" %
+ (unique_id,))
self.Attach()
@classmethod
if highest is None: # there are no minors in use at all
return 0
if highest >= cls._MAX_MINORS:
- logger.Error("Error: no free drbd minors!")
+ logging.error("Error: no free drbd minors!")
raise errors.BlockDeviceError("Can't find a free DRBD minor")
return highest + 1
"v08", meta_device, "0",
"dstate"])
if result.failed:
- logger.Error("Invalid meta device %s: %s" % (meta_device, result.output))
+ logging.error("Invalid meta device %s: %s", meta_device, result.output)
return False
return True
"""
result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "show"])
if result.failed:
- logger.Error("Can't display the drbd config: %s - %s" %
- (result.fail_reason, result.output))
+ logging.error("Can't display the drbd config: %s - %s",
+ result.fail_reason, result.output)
return None
return result.stdout
backend, meta, "0", "-e", "detach", "--create-device"]
result = utils.RunCmd(args)
if result.failed:
- logger.Error("Can't attach local disk: %s" % result.output)
+ logging.error("Can't attach local disk: %s", result.output)
return not result.failed
@classmethod
args.extend(["-a", hmac, "-x", secret])
result = utils.RunCmd(args)
if result.failed:
- logger.Error("Can't setup network for dbrd device: %s - %s" %
- (result.fail_reason, result.output))
+ logging.error("Can't setup network for dbrd device: %s - %s",
+ result.fail_reason, result.output)
return False
timeout = time.time() + 10
ok = True
break
if not ok:
- logger.Error("Timeout while configuring network")
+ logging.error("Timeout while configuring network")
return False
return True
raise errors.BlockDeviceError("We don't have two children: %s" %
self._children)
if self._children.count(None) == 2: # we don't actually have children :)
- logger.Error("Requested detach while detached")
+ logging.error("Requested detach while detached")
return
if len(devices) != 2:
raise errors.BlockDeviceError("We need two children in RemoveChildren")
"""
children_result = super(DRBD8, self).SetSyncSpeed(kbytes)
if self.minor is None:
- logger.Info("Instance not attached to a device")
+ logging.info("Instance not attached to a device")
return False
result = utils.RunCmd(["drbdsetup", self.dev_path, "syncer", "-r", "%d" %
kbytes])
if result.failed:
- logger.Error("Can't change syncer rate: %s - %s" %
- (result.fail_reason, result.output))
+ logging.error("Can't change syncer rate: %s - %s",
+ result.fail_reason, result.output)
return not result.failed and children_result
def GetProcStatus(self):
"""
if self.minor is None and not self.Attach():
- logger.Error("DRBD cannot attach to a device during open")
+ logging.error("DRBD cannot attach to a device during open")
return False
cmd = ["drbdsetup", self.dev_path, "primary"]
if force:
result = utils.RunCmd(cmd)
if result.failed:
msg = ("Can't make drbd device primary: %s" % result.output)
- logger.Error(msg)
+ logging.error(msg)
raise errors.BlockDeviceError(msg)
def Close(self):
"""
if self.minor is None and not self.Attach():
- logger.Info("Instance not attached to a device")
+ logging.info("Instance not attached to a device")
raise errors.BlockDeviceError("Can't find device")
result = utils.RunCmd(["drbdsetup", self.dev_path, "secondary"])
if result.failed:
msg = ("Can't switch drbd device to"
" secondary: %s" % result.output)
- logger.Error(msg)
+ logging.error(msg)
raise errors.BlockDeviceError(msg)
def Attach(self):
the attach if can return success.
"""
- for minor in self._GetUsedDevs():
+ for minor in (self._aminor,):
info = self._GetDevInfo(self._GetShowData(minor))
match_l = self._MatchesLocal(info)
match_r = self._MatchesNet(info)
res_r = self._AssembleNet(minor,
(self._lhost, self._lport,
self._rhost, self._rport),
- "C")
+ constants.DRBD_NET_PROTOCOL,
+ hmac=constants.DRBD_HMAC_ALG,
+ secret=self._secret
+ )
if res_r:
if self._MatchesNet(self._GetDevInfo(self._GetShowData(minor))):
break
# local storage (i.e. one or more of the _[lr](host|port) is
# None)
if (self._AssembleNet(minor, (self._lhost, self._lport,
- self._rhost, self._rport), "C") and
+ self._rhost, self._rport),
+ constants.DRBD_NET_PROTOCOL,
+ hmac=constants.DRBD_HMAC_ALG,
+ secret=self._secret) and
self._MatchesNet(self._GetDevInfo(self._GetShowData(minor)))):
break
"""
self.Attach()
if self.minor is not None:
- logger.Info("Already assembled")
+ logging.info("Already assembled")
return True
result = super(DRBD8, self).Assemble()
if not result:
return result
- minor = self._FindUnusedMinor()
+ # TODO: maybe completely tear-down the minor (drbdsetup ... down)
+ # before attaching our own?
+ minor = self._aminor
need_localdev_teardown = False
if self._children and self._children[0] and self._children[1]:
result = self._AssembleLocal(minor, self._children[0].dev_path,
result = self._AssembleNet(minor,
(self._lhost, self._lport,
self._rhost, self._rport),
- "C")
+ constants.DRBD_NET_PROTOCOL,
+ hmac=constants.DRBD_HMAC_ALG,
+ secret=self._secret)
if not result:
if need_localdev_teardown:
# we will ignore failures from this
- logger.Error("net setup failed, tearing down local device")
+ logging.error("net setup failed, tearing down local device")
self._ShutdownAll(minor)
return False
self._SetFromMinor(minor)
"""
result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "detach"])
if result.failed:
- logger.Error("Can't detach local device: %s" % result.output)
+ logging.error("Can't detach local device: %s", result.output)
return not result.failed
@classmethod
"""
result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "disconnect"])
if result.failed:
- logger.Error("Can't shutdown network: %s" % result.output)
+ logging.error("Can't shutdown network: %s", result.output)
return not result.failed
@classmethod
"""
result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "down"])
if result.failed:
- logger.Error("Can't shutdown drbd device: %s" % result.output)
+ logging.error("Can't shutdown drbd device: %s", result.output)
return not result.failed
def Shutdown(self):
"""
if self.minor is None and not self.Attach():
- logger.Info("DRBD device not attached to a device during Shutdown")
+ logging.info("DRBD device not attached to a device during Shutdown")
return True
if not self._ShutdownAll(self.minor):
return False
os.remove(self.dev_path)
return True
except OSError, err:
- logger.Error("Can't remove file '%s': %s"
- % (self.dev_path, err))
+ logging.error("Can't remove file '%s': %s", self.dev_path, err)
return False
def Attach(self):
if dev_type not in DEV_MAP:
raise errors.ProgrammerError("Invalid block device type '%s'" % dev_type)
device = DEV_MAP[dev_type](unique_id, children)
- if not device.Attach():
+ if not device.attached:
return None
return device
if dev_type not in DEV_MAP:
raise errors.ProgrammerError("Invalid block device type '%s'" % dev_type)
device = DEV_MAP[dev_type](unique_id, children)
- if not device.Attach():
+ if not device.attached:
device.Assemble()
- if not device.Attach():
+ if not device.attached:
raise errors.BlockDeviceError("Can't find a valid block device for"
" %s/%s/%s" %
(dev_type, unique_id, children))