[PATCH 2/5] Fix detection of lvm thinp setups. (#1013800)
David Lehman
dlehman at redhat.com
Mon Oct 14 17:44:20 UTC 2013
Instead of trying to figure out how to sort the lvs by attr (probably not
possible) just allow for adding building-block volumes on demand.
---
blivet/devices.py | 12 ++++-
blivet/devicetree.py | 136 +++++++++++++++++++++++++++++----------------------
2 files changed, 88 insertions(+), 60 deletions(-)
diff --git a/blivet/devices.py b/blivet/devices.py
index 6650086..d620eaf 100644
--- a/blivet/devices.py
+++ b/blivet/devices.py
@@ -2104,6 +2104,9 @@ class LVMVolumeGroupDevice(DMDevice):
self.reserved_percent = 0
self.reserved_space = 0
+ # this will have to be covered by the 20% pad for non-existent pools
+ self.poolMetaData = 0
+
# circular references, here I come
self._lvs = []
@@ -2319,6 +2322,9 @@ class LVMVolumeGroupDevice(DMDevice):
self._lvs.remove(lv)
+ if self.poolMetaData and not self.thinpools:
+ self.poolMetaData = 0
+
def _addPV(self, pv):
""" Add a PV to this VG. """
if pv in self.pvs:
@@ -2421,6 +2427,7 @@ class LVMVolumeGroupDevice(DMDevice):
log.debug("%s size is %dMB" % (self.name, self.size))
used = sum(lv.vgSpaceUsed for lv in self.lvs) + self.snapshotSpace
used += self.reservedSpace
+ used += self.poolMetaData
free = self.size - used
log.debug("vg %s has %dMB free" % (self.name, free))
return free
@@ -2788,7 +2795,7 @@ class LVMThinPoolDevice(LVMLogicalVolumeDevice):
def __init__(self, name, parents=None, size=None, uuid=None,
format=None, exists=False, sysfsPath='',
grow=None, maxsize=None, percent=None,
- metadatasize=None, chunksize=None):
+ metadatasize=None, chunksize=None, segType=None):
""" Create a LVMLogicalVolumeDevice instance.
Arguments:
@@ -2826,7 +2833,8 @@ class LVMThinPoolDevice(LVMLogicalVolumeDevice):
format=format, exists=exists,
sysfsPath=sysfsPath, grow=grow,
maxsize=maxsize,
- percent=percent)
+ percent=percent,
+ segType=segType)
self.metaDataSize = metadatasize or 0
self.chunkSize = chunksize or 0
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index 7bb746f..de19f6e 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -1180,26 +1180,22 @@ class DeviceTree(object):
% device.format.mapName)
def handleVgLvs(self, vg_device):
- """ Handle setup of the LV's in the vg_device
- return True if an LV was setup
- return False if there was an error, or no more LV's to setup
- """
- ret = False
+ """ Handle setup of the LV's in the vg_device. """
vg_name = vg_device.name
lv_names = vg_device.lv_names
lv_uuids = vg_device.lv_uuids
lv_sizes = vg_device.lv_sizes
- lv_attr = vg_device.lv_attr
+ lv_attrs = vg_device.lv_attr
lv_types = vg_device.lv_types
if not vg_device.complete:
log.warning("Skipping LVs for incomplete VG %s" % vg_name)
- return False
+ return
if not lv_names:
log.debug("no LVs listed for VG %s" % vg_name)
- return False
+ return
def lv_attr_cmp(a, b):
""" Sort so that mirror images come first and snapshots last. """
@@ -1220,85 +1216,96 @@ class DeviceTree(object):
else:
return 0
- # make a list of indices with mirror volumes up front and snapshots at
- # the end
- indices = range(len(lv_names))
- indices.sort(key=lambda i: lv_attr[i], cmp=lv_attr_cmp)
- raid = {}
- for index in indices:
+ def addLV(lv_name, lv_uuid, lv_attr, lv_size, lv_type):
lv_class = LVMLogicalVolumeDevice
- lv_name = lv_names[index]
lv_parents = [vg_device]
name = "%s-%s" % (vg_name, lv_name)
- if lv_attr[index][0] in 'Ss':
+
+ if self.getDeviceByName(name):
+ # some lvs may have been added on demand below
+ log.debug("already added %s" % name)
+ return
+
+ if lv_attr[0] in 'Ss':
log.info("found lvm snapshot volume '%s'" % name)
origin_name = devicelibs.lvm.lvorigin(vg_name, lv_name)
if not origin_name:
log.error("lvm snapshot '%s-%s' has unknown origin"
% (vg_name, lv_name))
- continue
+ return
- origin = self.getDeviceByName("%s-%s" % (vg_name,
- origin_name))
+ origin_device_name = "%s-%s" % (vg_name, origin_name)
+ origin = self.getDeviceByName(origin_device_name)
if not origin:
if origin_name.endswith("_vorigin]"):
log.info("snapshot volume '%s' has vorigin" % name)
- vg_device.voriginSnapshots[lv_name] = lv_sizes[index]
+ vg_device.voriginSnapshots[lv_name] = lv_size
+ return
else:
- log.warning("snapshot lv '%s' origin lv '%s-%s' "
- "not found" % (name,
- vg_name, origin_name))
- continue
+ oidx = lv_names.index(origin_name)
+ if oidx:
+ addLV(*lv_data[oidx])
+ origin = self.getDeviceByName(origin_device_name)
+
+ if origin is None:
+ log.warning("snapshot lv '%s' origin lv '%s' not "
+ "found" % (name, origin_device_name))
+ return
log.debug("adding %dMB to %s snapshot total"
% (lv_sizes[index], origin.name))
- origin.snapshotSpace += lv_sizes[index]
- continue
- elif lv_attr[index][0] == 'v':
+ origin.snapshotSpace += lv_size
+ return
+ elif lv_attr[0] == 'v':
# skip vorigins
- continue
- elif lv_attr[index][0] in 'Ii':
+ return
+ elif lv_attr[0] in 'Ii':
# mirror image
- lv_name = re.sub(r'_[rm]image.+', '', lv_name[1:-1])
- name = "%s-%s" % (vg_name, lv_name)
- if name not in raid:
- raid[name] = {"copies": 0, "log": 0, "meta": 0}
-
+ rname = re.sub(r'_[rm]image.+', '', lv_name[1:-1])
+ name = "%s-%s" % (vg_name, rname)
raid[name]["copies"] += 1
- continue
- elif lv_attr[index][0] == 'e':
+ return
+ elif lv_attr[0] == 'e':
+ if lv_name.endswith("_pmspare]"):
+ # spare metadata area for any thin pool that needs repair
+ vg_device.poolMetaData += lv_size
+ return
+
# raid metadata volume
lv_name = re.sub(r'_rmeta.+', '', lv_name[1:-1])
name = "%s-%s" % (vg_name, lv_name)
- raid[name]["meta"] += lv_sizes[index]
- continue
- elif lv_attr[index][0] == 'l':
+ raid[name]["meta"] += lv_size
+ return
+ elif lv_attr[0] == 'l':
# log volume
- lv_name = re.sub(r'_mlog.*', '', lv_name[1:-1])
- name = "%s-%s" % (vg_name, lv_name)
- if name not in mirrors:
- raid[name] = {"stripes": 0, "log": 0, "meta": 0}
-
- raid[name]["log"] = lv_sizes[index]
- continue
- elif lv_attr[index][0] == 't':
+ rname = re.sub(r'_mlog.*', '', lv_name[1:-1])
+ name = "%s-%s" % (vg_name, rname)
+ raid[name]["log"] = lv_size
+ return
+ elif lv_attr[0] == 't':
# thin pool
lv_class = LVMThinPoolDevice
- elif lv_attr[index][0] == 'V':
+ elif lv_attr[0] == 'V':
# thin volume
pool_name = devicelibs.lvm.thinlvpoolname(vg_name, lv_name)
- pool_device = self.getDeviceByName("%s-%s" % (vg_name,
- pool_name))
+ pool_device_name = "%s-%s" % (vg_name, pool_name)
+ pool_device = self.getDeviceByName(pool_device_name)
+ if pool_device is None:
+ pidx = lv_names.index(pool_name)
+ if pidx:
+ addLV(*lv_data[pidx])
+ pool_device = self.getDeviceByName(pool_device_name)
+
if pool_device is None:
raise DeviceTreeError("failed to look up thin pool")
+
lv_class = LVMThinLogicalVolumeDevice
lv_parents = [pool_device]
+ elif lv_attr[0] not in '-mMrR':
+ return
- lv_dev = self.getDeviceByUuid(lv_uuids[index])
+ lv_dev = self.getDeviceByUuid(lv_uuid)
if lv_dev is None:
- lv_uuid = lv_uuids[index]
- lv_size = lv_sizes[index]
- lv_type = lv_types[index]
lv_device = lv_class(lv_name, parents=lv_parents,
uuid=lv_uuid, size=lv_size,segType=lv_type,
exists=True)
@@ -1311,15 +1318,30 @@ class DeviceTree(object):
lv_info = udev_get_block_device(lv_device.sysfsPath)
if not lv_info:
log.error("failed to get udev data for lv %s" % lv_device.name)
- continue
+ return
# do format handling now
self.addUdevDevice(lv_info)
- ret = True
+ # make a list of indices with mirror volumes up front and snapshots at
+ # the end
+ indices = range(len(lv_names))
+ indices.sort(key=lambda i: lv_attrs[i], cmp=lv_attr_cmp)
+ lv_real_names = [n.replace("[", "").replace("]", "") for n in lv_names]
+ raid = dict([("%s-%s" % (vg_device.name,
+ n.replace("[", "").replace("]", "")),
+ {"copies": 0, "log": 0, "meta": 0})
+ for n in lv_names])
+ lv_data = zip(lv_names, lv_uuids, lv_attrs, lv_sizes, lv_types)
+ for i in range(len(lv_data)):
+ addLV(*lv_data[i])
for name, data in raid.items():
lv_dev = self.getDeviceByName(name)
+ if not lv_dev:
+ # hidden lv, eg: pool00_tdata
+ continue
+
lv_dev.copies = data["copies"]
lv_dev.metaDataSize = data["meta"]
lv_dev.logSize = data["log"]
@@ -1328,8 +1350,6 @@ class DeviceTree(object):
% (lv_dev.name, lv_dev.copies, lv_dev.metaDataSize,
lv_dev.logSize, lv_dev.vgSpaceUsed))
- return ret
-
def handleUdevLVMPVFormat(self, info, device):
log_method_call(self, name=device.name, type=device.format.type)
# lookup/create the VG and LVs
--
1.8.1.4
More information about the anaconda-patches
mailing list