From: Vratislav Podzimek <vpodzime(a)redhat.com>
When an LVM cache is created, an internal metadata LV is created for it. And for
LVM that also means that a special pmspare LV with a size greater or equal to
the size of the metadata LV has to exist (and thus may be created) in the same
VG. We don't want to bother user code with these calculations and thus we should
subtract this space from the requested cache's size.
---
blivet/devices/lvm.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 80a04ab..4780d12 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -1947,6 +1947,11 @@ def __init__(self, cached_lv, size=None, md_size=None, exists=False, pvs=None, m
if not exists and not md_size:
default_md_size = Size(blockdev.lvm.cache_get_default_md_size(size))
self._size = size - default_md_size
+ # if we are going to cause a pmspare LV allocation or growth, we
+ # should account for it
+ if cached_lv.vg.pmspare_size < default_md_size:
+ self._size -= default_md_size - cached_lv.vg.pmspare_size
+ self._size = cached_lv.vg.align(self._size)
self._md_size = default_md_size
else:
self._size = size
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/e89bf610db622be915f9b739a8270e…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
Creating an LV means some extents were allocated from its VG's PVs. In order to
prevent us from working with old values we need to make sure fresh values are
fetched.
---
blivet/devices/lvm.py | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 6766332..80a04ab 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -1002,6 +1002,19 @@ def _create(self):
blockdev.lvm.cache_create_cached_lv(self.vg.name, self._name, self.size, self.cache.size, self.cache.md_size,
mode, 0, util.dedup_list(slow_pvs + fast_pvs), fast_pvs)
+ def _post_create(self):
+ super()._post_create()
+ # update the free space info of the PVs this LV could have taken space
+ # from (either specified or potentially all PVs from the VG)
+ if self._pv_specs:
+ used_pvs = [spec.pv for spec in self._pv_specs]
+ else:
+ used_pvs = self.vg.pvs
+ for pv in used_pvs:
+ # None means "not set" and triggers a dynamic fetch of the actual
+ # value when queried
+ pv.format.free = None
+
def _pre_destroy(self):
StorageDevice._pre_destroy(self)
# set up the vg's pvs so lvm can remove the lv
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/fb2f2119320d12dac456c82e8e02fb…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
In order to make sure we are working with something we understand.
---
blivet/devices/lvm.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index c87156d..6766332 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -603,6 +603,8 @@ def __init__(self, name, parents=None, size=None, uuid=None, seg_type=None,
"""
if not exists:
+ if seg_type not in [None, "linear"] + [level.name for level in lvm.raid_levels]:
+ raise ValueError("Invalid or unsupported segment type: %s" % seg_type)
if seg_type and seg_type != "linear" and not pvs:
raise ValueError("List of PVs has to be given for every non-linear LV")
elif (not seg_type or seg_type == "linear") and pvs:
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/3b44a0f9dccafef4696013739f3634…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
Useful for testing as well as for users wondering how to do something like this.
---
examples/lvm_cache.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100644 examples/lvm_cache.py
diff --git a/examples/lvm_cache.py b/examples/lvm_cache.py
new file mode 100644
index 0000000..e0c5e58
--- /dev/null
+++ b/examples/lvm_cache.py
@@ -0,0 +1,66 @@
+import os
+
+from examples.common import print_devices
+
+import blivet
+from blivet.size import Size
+from blivet.util import set_up_logging, create_sparse_tempfile
+from blivet.devices.lvm import LVMCacheRequest
+
+set_up_logging()
+b = blivet.Blivet() # create an instance of Blivet (don't add system devices)
+
+# create a disk image file on which to create new devices
+disk1_file = create_sparse_tempfile("disk1", Size("100GiB"))
+b.config.disk_images["disk1"] = disk1_file
+disk2_file = create_sparse_tempfile("disk2", Size("100GiB"))
+b.config.disk_images["disk2"] = disk2_file
+
+b.reset()
+
+try:
+ disk1 = b.devicetree.get_device_by_name("disk1")
+ disk2 = b.devicetree.get_device_by_name("disk2")
+
+ b.initialize_disk(disk1)
+ b.initialize_disk(disk2)
+
+ pv = b.new_partition(size=Size("50GiB"), fmt_type="lvmpv", parents=[disk1])
+ b.create_device(pv)
+ pv2 = b.new_partition(size=Size("50GiB"), fmt_type="lvmpv", parents=[disk2])
+ b.create_device(pv2)
+
+ # allocate the partitions (decide where and on which disks they'll reside)
+ blivet.partitioning.do_partitioning(b)
+
+ vg = b.new_vg(parents=[pv, pv2])
+ b.create_device(vg)
+
+ # new lv with base size 5GiB and unbounded growth and an ext4 filesystem
+ dev = b.new_lv(fmt_type="ext4", size=Size("5GiB"), grow=True,
+ parents=[vg], name="unbounded")
+ b.create_device(dev)
+
+ # new lv with base size 5GiB and growth up to 15GiB and an ext4 filesystem
+ dev = b.new_lv(fmt_type="ext4", size=Size("5GiB"), grow=True,
+ maxsize=Size("15GiB"), parents=[vg], name="bounded")
+ b.create_device(dev)
+
+ # new lv with a fixed size of 2GiB formatted as swap space
+ cache_spec = LVMCacheRequest(size=Size("1GiB"), pvs=[pv2])
+ dev = b.new_lv(fmt_type="ext4", size=Size("2GiB"), parents=[vg], name="cached", cache_request=cache_spec)
+ b.create_device(dev)
+
+ # allocate the growable lvs
+ blivet.partitioning.grow_lvm(b)
+ print_devices(b)
+
+ # write the new partitions to disk and format them as specified
+ b.do_it()
+ print_devices(b)
+ input("Check the state and hit ENTER to trigger cleanup")
+finally:
+ b.devicetree.teardown_disk_images()
+ os.unlink(disk1_file)
+ os.unlink(disk2_file)
+
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/04cd39780dbce2d3d09a7590ea2fd9…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
LVM complains about a PV appearing multiple times in the list of PVs to use.
Add and use a function for deduplicating things in a list (keeping the ordering
of the items).
---
blivet/devices/lvm.py | 10 ++++++----
blivet/util.py | 11 +++++++++++
tests/util_test.py | 9 +++++++++
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index fab40e1..c87156d 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -991,12 +991,14 @@ def _create(self):
all_fast_pvs_names |= set(pv.name for pv in lv.cache.fast_pvs)
slow_pvs = [pv.path for pv in self.vg.pvs if pv.name not in all_fast_pvs_names]
+ slow_pvs = util.dedup_list(slow_pvs)
+
# VG name, LV name, data size, cache size, metadata size, mode, flags, slow PVs, fast PVs
- # XXX: we need to pass slow_pvs+fast_pvs as slow PVs because parts
- # of the fast PVs may be required for allocation of the LV (it may
- # span over the slow PVs and parts of fast PVs)
+ # XXX: we need to pass slow_pvs+fast_pvs (without duplicates) as slow PVs because parts of the
+ # fast PVs may be required for allocation of the LV (it may span over the slow PVs and parts of
+ # fast PVs)
blockdev.lvm.cache_create_cached_lv(self.vg.name, self._name, self.size, self.cache.size, self.cache.md_size,
- mode, 0, slow_pvs + fast_pvs, fast_pvs)
+ mode, 0, util.dedup_list(slow_pvs + fast_pvs), fast_pvs)
def _pre_destroy(self):
StorageDevice._pre_destroy(self)
diff --git a/blivet/util.py b/blivet/util.py
index 69caaa1..7b8d2a6 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -714,6 +714,17 @@ def compare(first, second):
else:
return (first > second) - (first < second)
+
+def dedup_list(alist):
+ seen = set()
+ ret = []
+ for item in alist:
+ if item not in seen:
+ ret.append(item)
+ seen.add(item)
+ return ret
+
+
##
# Convenience functions for examples and tests
##
diff --git a/tests/util_test.py b/tests/util_test.py
index 7155cbe..d6792fe 100644
--- a/tests/util_test.py
+++ b/tests/util_test.py
@@ -24,6 +24,15 @@ def test_power_of_two(self):
self.assertFalse(util.power_of_two(2 ** i + 1), msg=i)
self.assertFalse(util.power_of_two(2 ** i - 1), msg=i)
+ def test_dedup_list(self):
+ # no duplicates, no change
+ self.assertEqual([1, 2, 3, 4], util.dedup_list([1, 2, 3, 4]))
+ # empty list no issue
+ self.assertEqual([], util.dedup_list([]))
+
+ # real deduplication
+ self.assertEqual([1, 2, 3, 4, 5, 6], util.dedup_list([1, 2, 3, 4, 2, 2, 2, 1, 3, 5, 3, 6, 6, 2, 3, 1, 5]))
+
class TestDefaultNamedtuple(unittest.TestCase):
def test_default_namedtuple(self):
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/feff86877205771b846730cfb096cd…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
It is shorter, faster and more reliable. Using pv.name was a remnant of
development version of the LVM cache support that worked with PV names instead
of PV (StorageDevice) objects.
---
blivet/devices/lvm.py | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 5b84296..fab40e1 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -977,14 +977,7 @@ def _create(self):
type=self.seg_type, pv_list=pvs)
else:
mode = blockdev.lvm.cache_get_mode_from_str(self.cache.mode)
- # prepare the list of fast PV devices
- fast_pvs = []
- for pv_name in (pv.name for pv in self.cache.fast_pvs):
- # make sure we have the full device paths
- if not pv_name.startswith("/dev/"):
- fast_pvs.append("/dev/%s" % pv_name)
- else:
- fast_pvs.append(pv_name)
+ fast_pvs = [pv.path for pv in self.cache.fast_pvs]
if self._pv_specs:
# (slow) PVs specified for this LV
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/29098c0aa6789eb944bb939da5c7a7…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
Now that we keep track of available space in the PVs we need to take into
account LVM caches because those specify PVs and thus we need to make sure that
they really fit in somewhere. Also the users need to know how much space they
still have available in their PVs if they add a cache to their LV(s).
---
blivet/devices/lvm.py | 95 +++++++++++++++++++++++++++++++++++++++------------
1 file changed, 73 insertions(+), 22 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index bf7717e..5b84296 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -311,15 +311,19 @@ def _add_log_vol(self, lv):
origin.snapshots.append(lv)
# PV space accounting
- pv_sizes = lv.pv_space_used
- if not lv.exists and pv_sizes:
- for size_spec in pv_sizes:
+ if not lv.exists:
+ # create a copy of the list so that we don't modify the origin below
+ pv_sizes = lv.pv_space_used[:]
+ if lv.cached:
+ pv_sizes.extend(lv.cache.pv_space_used)
+ if pv_sizes:
# check that we have enough space in the PVs for the LV and
# account for it
- if size_spec.pv.format.free < size_spec.size:
- msg = "not enough space in the '%s' PV for the '%s' LV's extents" % (size_spec.pv.name, lv.name)
- raise errors.DeviceError(msg)
- size_spec.pv.format.free -= size_spec.size
+ for size_spec in pv_sizes:
+ if size_spec.pv.format.free < size_spec.size:
+ msg = "not enough space in the '%s' PV for the '%s' LV's extents" % (size_spec.pv.name, lv.name)
+ raise errors.DeviceError(msg)
+ size_spec.pv.format.free -= size_spec.size
def _remove_log_vol(self, lv):
""" Remove an LV from this VG. """
@@ -334,7 +338,9 @@ def _remove_log_vol(self, lv):
origin.snapshots.remove(lv)
# PV space accounting
- pv_sizes = lv.pv_space_used
+ pv_sizes = lv.pv_space_used[:]
+ if lv.cached:
+ pv_sizes.extend(lv.cache.pv_space_used)
if not lv.exists and pv_sizes:
for size_spec in pv_sizes:
size_spec.pv.format.free += size_spec.size
@@ -642,7 +648,7 @@ def __init__(self, name, parents=None, size=None, uuid=None, seg_type=None,
if cache_request and not self.exists:
self._cache = LVMCache(self, size=cache_request.size, exists=False,
- fast_pvs=cache_request.fast_devs, mode=cache_request.mode)
+ pvs=cache_request.fast_devs, mode=cache_request.mode)
self._pv_specs = []
pvs = pvs or []
@@ -1904,7 +1910,7 @@ class LVMCache(Cache):
"""Class providing the cache-related functionality of a cached LV"""
- def __init__(self, cached_lv, size=None, md_size=None, exists=False, fast_pvs=None, mode=None):
+ def __init__(self, cached_lv, size=None, md_size=None, exists=False, pvs=None, mode=None):
"""
:param cached_lv: the LV the cache functionality of which to provide
:type cached_lv: :class:`LVMLogicalVolumeDevice`
@@ -1916,8 +1922,8 @@ def __init__(self, cached_lv, size=None, md_size=None, exists=False, fast_pvs=No
size dynamically) or None to use the default (see note below)
:type md_size: :class:`~.size.Size` or NoneType
:param bool exists: whether the cache exists or not
- :param fast_pvs: PVs to allocate the cache on/from (ignored for existing)
- :type fast_pvs: list of :class:`~.devices.storage.StorageDevice`
+ :param pvs: PVs to allocate the cache on/from (ignored for existing)
+ :type pvs: list of :class:`LVPVSpec`
:param str mode: desired mode for non-existing cache (ignored for existing)
.. note::
@@ -1936,12 +1942,34 @@ def __init__(self, cached_lv, size=None, md_size=None, exists=False, fast_pvs=No
self._size = size
self._md_size = md_size
self._exists = exists
+ self._mode = None
+ self._pv_specs = []
if not exists:
self._mode = mode or "writethrough"
- self._fast_pvs = fast_pvs
- else:
- self._mode = None
- self._fast_pvs = None
+ for pv_spec in pvs:
+ if isinstance(pv_spec, LVPVSpec):
+ self._pv_specs.append(pv_spec)
+ elif isinstance(pv_spec, StorageDevice):
+ self._pv_specs.append(LVPVSpec(pv_spec, Size(0)))
+ self._assign_pv_space()
+
+ def _assign_pv_space(self):
+ # calculate the size of space that we need to place somewhere
+ space_to_assign = self.size + self.md_size - sum(spec.size for spec in self._pv_specs)
+
+ # skip the PVs that already have some chunk of the space assigned
+ for spec in (spec for spec in self._pv_specs if not spec.size):
+ if spec.pv.format.free >= space_to_assign:
+ # enough space in this PV, put everything in there and quit
+ spec.size = space_to_assign
+ space_to_assign = Size(0)
+ break
+ elif spec.pv.format.free > 0:
+ # some space, let's use it and move on to another PV (if any)
+ spec.size = spec.pv.format.free
+ space_to_assign -= spec.pv.format.free
+ if space_to_assign > 0:
+ raise ValueError("Not enough free space in the PVs for this cache: %s short" % space_to_assign)
@property
def size(self):
@@ -2000,7 +2028,16 @@ def cache_device_name(self):
@property
def fast_pvs(self):
- return self._fast_pvs
+ return [spec.pv for spec in self._pv_specs]
+
+ @property
+ def pv_space_used(self):
+ """
+ :returns: space to be occupied by the cache on its LV's VG's PVs (one has to love LVM)
+ :rtype: list of LVPVSpec
+
+ """
+ return self._pv_specs
def detach(self):
vg_name = self._cached_lv.vg.name
@@ -2083,18 +2120,23 @@ class LVMCacheRequest(CacheRequest):
"""Class representing the LVM cache creation request"""
- def __init__(self, size, fast_pvs, mode=None):
+ def __init__(self, size, pvs, mode=None):
"""
:param size: requested size of the cache
:type size: :class:`~.size.Size`
- :param fast_pvs: PVs to allocate the cache on/from
- :type fast_pvs: list of :class:`~.devices.storage.StorageDevice`
+ :param pvs: PVs to allocate the cache on/from
+ :type pvs: list of (:class:`~.devices.storage.StorageDevice` or :class:`LVPVSpec`)
:param str mode: requested mode for the cache (``None`` means the default is used)
"""
self._size = size
- self._fast_pvs = fast_pvs
self._mode = mode or "writethrough"
+ self._pv_specs = []
+ for pv_spec in pvs:
+ if isinstance(pv_spec, LVPVSpec):
+ self._pv_specs.append(pv_spec)
+ elif isinstance(pv_spec, StorageDevice):
+ self._pv_specs.append(LVPVSpec(pv_spec, Size(0)))
@property
def size(self):
@@ -2102,7 +2144,16 @@ def size(self):
@property
def fast_devs(self):
- return self._fast_pvs
+ return [spec.pv for spec in self._pv_specs]
+
+ @property
+ def pv_space_requests(self):
+ """
+ :returns: space to be occupied by the cache on its LV's VG's PVs (one has to love LVM)
+ :rtype: list of LVPVSpec
+
+ """
+ return self._pv_specs
@property
def mode(self):
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/51c9ff933c0ebde13f7005be64f8c4…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
lv.size reports the size of the LV not the space occupied in the VG, that's what
data_vg_space_used is for. Under the same logic lv.metadata_size should report
the size of the metadata space LV has available leaving
lv.metadata_vg_space_used for reporting how much space from the VG the metadata
part(s) of the LV take.
If the LV exists, we should just go through the internal metadata LVs and sum
their sizes because that's the actual/real value.
Also document the property.
Please note that no changes are needed outside of these two properties because
they are already used properly and this just fixes the values such places in
code calculate with (like metadata_size passed to blockdev.thpoolcreate() or
calculation of the pmspare LV's size).
---
blivet/devices/lvm.py | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 44d51db..bf7717e 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -713,18 +713,15 @@ def log_size(self):
@property
def metadata_size(self):
- if self._metadata_size:
- if self.is_raid_lv:
- zero_superblock = lambda x: Size(0)
- return self._raid_level.get_space(self._metadata_size, self._num_raid_pvs,
- superblock_size_func=zero_superblock)
- else:
- return self._metadata_size
- elif self.cached:
- return self.cache.md_size
+ """ Size of the meta data space this LV has available (see also :property:`metadata_vg_space_used`) """
+ if self.exists:
+ md_lvs = (int_lv for int_lv in self._internal_lvs if isinstance(int_lv, LVMMetadataLogicalVolumeDevice))
+ return Size(sum(lv.size for lv in md_lvs))
- md_lvs = (int_lv for int_lv in self._internal_lvs if isinstance(int_lv, LVMMetadataLogicalVolumeDevice))
- return Size(sum(lv.size for lv in md_lvs))
+ ret = self._metadata_size
+ if self.cached:
+ ret += self.cache.md_size
+ return ret
def __repr__(self):
s = DMDevice.__repr__(self)
@@ -797,8 +794,22 @@ def data_vg_space_used(self):
@property
def metadata_vg_space_used(self):
- """ Space occupied by the metadata part of this LV, not including snapshots """
- return self.log_size + self.metadata_size
+ """ Space occupied by the metadata part(s) of this LV, not including snapshots """
+ non_raid_base = self.metadata_size + self.log_size
+ if non_raid_base and self.is_raid_lv:
+ zero_superblock = lambda x: Size(0)
+ try:
+ return self._raid_level.get_space(non_raid_base, self._num_raid_pvs,
+ superblock_size_func=zero_superblock)
+ except errors.RaidError:
+ # Too few PVs for the segment type (RAID level), we must have
+ # incomplete information about the current LVM
+ # configuration. Let's just default to the basic size for
+ # now. Later calls to this property will provide better results.
+ # TODO: add pv_count field to blockdev.LVInfo and this class
+ return non_raid_base
+
+ return non_raid_base
@property
def vg_space_used(self):
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/65935d4cf9c089e916fe348274573b…
From: Vratislav Podzimek <vpodzime(a)redhat.com>
The word "copies" is accurate together with mirror/RAID1 RAID, but it's
misleading with other RAID levels LVM supports. The property doesn't seem to be
accessed anywhere outside the class so let's just replace it with a private
property with a more accurate name.
Also give incomplete/inaccurate information if we have incomplete/inaccurate
information instead of erroring out.
---
blivet/devices/lvm.py | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 9a75635..44d51db 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -699,9 +699,12 @@ def is_raid_lv(self):
return self.seg_type != "linear" and self._raid_level
@property
- def copies(self):
- image_lvs = [int_lv for int_lv in self._internal_lvs if isinstance(int_lv, LVMImageLogicalVolumeDevice)]
- return len(image_lvs) or 1
+ def _num_raid_pvs(self):
+ if self.exists:
+ image_lvs = [int_lv for int_lv in self._internal_lvs if isinstance(int_lv, LVMImageLogicalVolumeDevice)]
+ return len(image_lvs) or 1
+ else:
+ return len(self._pv_specs)
@property
def log_size(self):
@@ -713,7 +716,7 @@ def metadata_size(self):
if self._metadata_size:
if self.is_raid_lv:
zero_superblock = lambda x: Size(0)
- return self._raid_level.get_space(self._metadata_size, len(self._pv_specs),
+ return self._raid_level.get_space(self._metadata_size, self._num_raid_pvs,
superblock_size_func=zero_superblock)
else:
return self._metadata_size
@@ -727,10 +730,9 @@ def __repr__(self):
s = DMDevice.__repr__(self)
s += (" VG device = %(vgdev)r\n"
" segment type = %(type)s percent = %(percent)s\n"
- " mirror copies = %(copies)d"
" VG space used = %(vgspace)s" %
{"vgdev": self.vg, "percent": self.req_percent,
- "copies": self.copies, "type": self.seg_type,
+ "type": self.seg_type,
"vgspace": self.vg_space_used})
return s
@@ -738,8 +740,7 @@ def __repr__(self):
def dict(self):
d = super(LVMLogicalVolumeDevice, self).dict
if self.exists:
- d.update({"copies": self.copies,
- "vgspace": self.vg_space_used})
+ d.update({"vgspace": self.vg_space_used})
else:
d.update({"percent": self.req_percent})
@@ -747,7 +748,7 @@ def dict(self):
@property
def mirrored(self):
- return self.copies > 1
+ return self._raid_level and self._raid_level.has_redundancy()
def _set_size(self, size):
if not isinstance(size, Size):
@@ -781,8 +782,16 @@ def data_vg_space_used(self):
rounded_size = self.vg.align(self.size, roundup=True)
if self.is_raid_lv:
zero_superblock = lambda x: Size(0)
- return self._raid_level.get_space(rounded_size, len(self._pv_specs),
- superblock_size_func=zero_superblock)
+ try:
+ return self._raid_level.get_space(rounded_size, self._num_raid_pvs,
+ superblock_size_func=zero_superblock)
+ except errors.RaidError:
+ # Too few PVs for the segment type (RAID level), we must have
+ # incomplete information about the current LVM
+ # configuration. Let's just default to the basic size for
+ # now. Later calls to this property will provide better results.
+ # TODO: add pv_count field to blockdev.LVInfo and this class
+ return rounded_size
else:
return rounded_size
@@ -1254,10 +1263,9 @@ def __repr__(self):
s += (" parent LV = %r\n" % self.parent_lv)
s += (" VG device = %(vgdev)r\n"
" segment type = %(type)s percent = %(percent)s\n"
- " mirror copies = %(copies)d"
" VG space used = %(vgspace)s" %
{"vgdev": self.vg, "percent": self.req_percent,
- "copies": self.copies, "type": self.seg_type,
+ "type": self.seg_type,
"vgspace": self.vg_space_used})
return s
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/4a718424a1c6b3b970dc14da777717…