-#!/usr/bin/python
+#
#
# Copyright (C) 2006, 2007 Google Inc.
after assembly we'll have our correct major/minor.
"""
-
STATUS_UNKNOWN = 0
STATUS_EXISTING = 1
STATUS_STANDBY = 2
return min_percent, max_time, is_degraded
+ def SetInfo(self, text):
+ """Update metadata with info text.
+
+ Only supported for some device types.
+
+ """
+ for child in self._children:
+ child.SetInfo(text)
+
+
def __repr__(self):
return ("<%s: unique_id: %s, children: %s, %s:%s, %s>" %
(self.__class__, self.unique_id, self._children,
vg_name, lv_name = unique_id
pvs_info = cls.GetPVInfo(vg_name)
if not pvs_info:
- raise errors.BlockDeviceError, ("Can't compute PV info for vg %s" %
- vg_name)
+ raise errors.BlockDeviceError("Can't compute PV info for vg %s" %
+ vg_name)
pvs_info.sort()
pvs_info.reverse()
# The size constraint should have been checked from the master before
# calling the create function.
if free_size < size:
- raise errors.BlockDeviceError, ("Not enough free space: required %s,"
- " available %s" % (size, free_size))
+ raise errors.BlockDeviceError("Not enough free space: required %s,"
+ " available %s" % (size, free_size))
result = utils.RunCmd(["lvcreate", "-L%dm" % size, "-n%s" % lv_name,
vg_name] + pvlist)
if result.failed:
Returns:
list of (free_space, name) with free_space in mebibytes
+
"""
command = ["pvs", "--noheadings", "--nosuffix", "--units=m",
"-opv_name,vg_name,pv_free,pv_attr", "--unbuffered",
"""Create a snapshot copy of an lvm block device.
"""
-
snap_name = self._lv_name + ".snap"
# remove existing snapshot if found
pvs_info = self.GetPVInfo(self._vg_name)
if not pvs_info:
- raise errors.BlockDeviceError, ("Can't compute PV info for vg %s" %
- self._vg_name)
+ raise errors.BlockDeviceError("Can't compute PV info for vg %s" %
+ self._vg_name)
pvs_info.sort()
pvs_info.reverse()
free_size, pv_name = pvs_info[0]
if free_size < size:
- raise errors.BlockDeviceError, ("Not enough free space: required %s,"
- " available %s" % (size, free_size))
+ raise errors.BlockDeviceError("Not enough free space: required %s,"
+ " available %s" % (size, free_size))
result = utils.RunCmd(["lvcreate", "-L%dm" % size, "-s",
"-n%s" % snap_name, self.dev_path])
if result.failed:
- raise errors.BlockDeviceError, ("command: %s error: %s" %
- (result.cmd, result.fail_reason))
+ raise errors.BlockDeviceError("command: %s error: %s" %
+ (result.cmd, result.fail_reason))
return snap_name
+ def SetInfo(self, text):
+ """Update metadata with info text.
+
+ """
+ BlockDev.SetInfo(self, text)
+
+ # Replace invalid characters
+ text = re.sub('^[^A-Za-z0-9_+.]', '_', text)
+ text = re.sub('[^-A-Za-z0-9_+.]', '_', text)
+
+ # Only up to 128 characters are allowed
+ text = text[:128]
+
+ result = utils.RunCmd(["lvchange", "--addtag", text,
+ self.dev_path])
+ if result.failed:
+ raise errors.BlockDeviceError("Command: %s error: %s" %
+ (result.cmd, result.fail_reason))
+
+
class MDRaid1(BlockDev):
"""raid1 device implemented via md.
kv = line.split(" : ", 1)
if kv:
if kv[0] == "UUID":
- retval["uuid"] = kv[1]
+ retval["uuid"] = kv[1].split()[0]
elif kv[0] == "State":
retval["state"] = kv[1].split(", ")
return retval
return None
+ @staticmethod
+ def _ZeroSuperblock(dev_path):
+ """Zero the possible locations for an MD superblock.
+
+ The zero-ing can't be done via ``mdadm --zero-superblock`` as that
+ fails in versions 2.x with the same error code as non-writable
+ device.
+
+ The superblocks are located at (negative values are relative to
+ the end of the block device):
+ - -128k to end for version 0.90 superblock
+ - -8k to -12k for version 1.0 superblock (included in the above)
+ - 0k to 4k for version 1.1 superblock
+ - 4k to 8k for version 1.2 superblock
+
+ To cover all situations, the zero-ing will be:
+ - 0k to 128k
+ - -128k to end
+
+ As such, the minimum device size must be 128k, otherwise we'll get
+ I/O errors.
+
+ Note that this function depends on the fact that one can open,
+ read and write block devices normally.
+
+ """
+ overwrite_size = 128 * 1024
+ empty_buf = '\0' * overwrite_size
+ fd = open(dev_path, "r+")
+ try:
+ fd.seek(0, 0)
+ p1 = fd.tell()
+ fd.write(empty_buf)
+ p2 = fd.tell()
+ logger.Debug("Zeroed %s from %d to %d" % (dev_path, p1, p2))
+ fd.seek(-overwrite_size, 2)
+ p1 = fd.tell()
+ fd.write(empty_buf)
+ p2 = fd.tell()
+ logger.Debug("Zeroed %s from %d to %d" % (dev_path, p1, p2))
+ finally:
+ fd.close()
+
@classmethod
def Create(cls, unique_id, children, size):
"""Create a new MD raid1 array.
if not isinstance(i, BlockDev):
raise ValueError("Invalid member in MDRaid1 dev: %s" % type(i))
for i in children:
- result = utils.RunCmd(["mdadm", "--zero-superblock", "--force",
- i.dev_path])
- if result.failed:
- logger.Error("Can't zero superblock: %s" % result.fail_reason)
+ try:
+ cls._ZeroSuperblock(i.dev_path)
+ except EnvironmentError, err:
+ logger.Error("Can't zero superblock for %s: %s" %
+ (i.dev_path, str(err)))
return None
minor = cls._FindUnusedMinor()
result = utils.RunCmd(["mdadm", "--create", "/dev/md%d" % minor,
[dev.dev_path for dev in children])
if result.failed:
- logger.Error("Can't create md: %s" % result.fail_reason)
+ logger.Error("Can't create md: %s: %s" % (result.fail_reason,
+ result.output))
return None
info = cls._GetDevInfo(minor)
if not info or not "uuid" in info:
"""
if self.minor is None and not self.Attach():
- raise errors.BlockDeviceError, "Can't attach to device"
+ raise errors.BlockDeviceError("Can't attach to device")
if device.dev_path is None:
- raise errors.BlockDeviceError, "New child is not initialised"
+ raise errors.BlockDeviceError("New child is not initialised")
result = utils.RunCmd(["mdadm", "-a", self.dev_path, device.dev_path])
if result.failed:
- raise errors.BlockDeviceError, ("Failed to add new device to array: %s" %
- result.output)
+ raise errors.BlockDeviceError("Failed to add new device to array: %s" %
+ result.output)
new_len = len(self._children) + 1
result = utils.RunCmd(["mdadm", "--grow", self.dev_path, "-n", new_len])
if result.failed:
- raise errors.BlockDeviceError, ("Can't grow md array: %s" %
- result.output)
+ raise errors.BlockDeviceError("Can't grow md array: %s" %
+ result.output)
self._children.append(device)
"""
if self.minor is None and not self.Attach():
- raise errors.BlockDeviceError, "Can't attach to device"
+ raise errors.BlockDeviceError("Can't attach to device")
if len(self._children) == 1:
- raise errors.BlockDeviceError, ("Can't reduce member when only one"
- " child left")
+ raise errors.BlockDeviceError("Can't reduce member when only one"
+ " child left")
for device in self._children:
if device.dev_path == dev_path:
break
else:
- raise errors.BlockDeviceError, "Can't find child with this path"
+ raise errors.BlockDeviceError("Can't find child with this path")
new_len = len(self._children) - 1
result = utils.RunCmd(["mdadm", "-f", self.dev_path, dev_path])
if result.failed:
- raise errors.BlockDeviceError, ("Failed to mark device as failed: %s" %
- result.output)
+ raise errors.BlockDeviceError("Failed to mark device as failed: %s" %
+ result.output)
# it seems here we need a short delay for MD to update its
# superblocks
time.sleep(0.5)
result = utils.RunCmd(["mdadm", "-r", self.dev_path, dev_path])
if result.failed:
- raise errors.BlockDeviceError, ("Failed to remove device from array:"
- " %s" % result.output)
+ raise errors.BlockDeviceError("Failed to remove device from array:"
+ " %s" % result.output)
result = utils.RunCmd(["mdadm", "--grow", "--force", self.dev_path,
"-n", new_len])
if result.failed:
- raise errors.BlockDeviceError, ("Can't shrink md array: %s" %
- result.output)
+ raise errors.BlockDeviceError("Can't shrink md array: %s" %
+ result.output)
self._children.remove(device)
self.unique_id, "/dev/md%d" % free_minor] +
[bdev.dev_path for bdev in self._children])
if result.failed:
- logger.Error("Can't assemble MD array: %s" % result.fail_reason)
+ logger.Error("Can't assemble MD array: %s: %s" %
+ (result.fail_reason, result.output))
self.minor = None
else:
self.minor = free_minor
minor = self._FindUnusedMinor()
if minor is None:
- raise errors.BlockDeviceError, "Not enough free minors for DRBD!"
+ raise errors.BlockDeviceError("Not enough free minors for DRBD!")
need_localdev_teardown = False
if self._children[0]:
result = self._AssembleLocal(minor, self._children[0].dev_path,