import python-blivet-3.2.2-10.el8
This commit is contained in:
parent
e0d4f52514
commit
534eff7ab7
459
SOURCES/0012-xfs-grow-support.patch
Normal file
459
SOURCES/0012-xfs-grow-support.patch
Normal file
@ -0,0 +1,459 @@
|
||||
From 433d863cd8a57e5fc30948ff905e6a477ed5f17c Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 14 Jul 2020 11:27:08 +0200
|
||||
Subject: [PATCH 1/4] Add support for XFS format grow
|
||||
|
||||
---
|
||||
blivet/formats/fs.py | 2 ++
|
||||
blivet/tasks/availability.py | 1 +
|
||||
blivet/tasks/fsresize.py | 54 ++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 57 insertions(+)
|
||||
|
||||
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
|
||||
index eee15aaa..12cb9885 100644
|
||||
--- a/blivet/formats/fs.py
|
||||
+++ b/blivet/formats/fs.py
|
||||
@@ -1089,11 +1089,13 @@ class XFS(FS):
|
||||
_formattable = True
|
||||
_linux_native = True
|
||||
_supported = True
|
||||
+ _resizable = True
|
||||
_packages = ["xfsprogs"]
|
||||
_info_class = fsinfo.XFSInfo
|
||||
_mkfs_class = fsmkfs.XFSMkfs
|
||||
_readlabel_class = fsreadlabel.XFSReadLabel
|
||||
_size_info_class = fssize.XFSSize
|
||||
+ _resize_class = fsresize.XFSResize
|
||||
_sync_class = fssync.XFSSync
|
||||
_writelabel_class = fswritelabel.XFSWriteLabel
|
||||
_writeuuid_class = fswriteuuid.XFSWriteUUID
|
||||
diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py
|
||||
index b6b5955a..df62780c 100644
|
||||
--- a/blivet/tasks/availability.py
|
||||
+++ b/blivet/tasks/availability.py
|
||||
@@ -455,5 +455,6 @@ TUNE2FS_APP = application_by_version("tune2fs", E2FSPROGS_VERSION)
|
||||
XFSADMIN_APP = application("xfs_admin")
|
||||
XFSDB_APP = application("xfs_db")
|
||||
XFSFREEZE_APP = application("xfs_freeze")
|
||||
+XFSRESIZE_APP = application("xfs_growfs")
|
||||
|
||||
MOUNT_APP = application("mount")
|
||||
diff --git a/blivet/tasks/fsresize.py b/blivet/tasks/fsresize.py
|
||||
index e7e26984..12c0367f 100644
|
||||
--- a/blivet/tasks/fsresize.py
|
||||
+++ b/blivet/tasks/fsresize.py
|
||||
@@ -20,7 +20,10 @@
|
||||
# Red Hat Author(s): Anne Mulhern <amulhern@redhat.com>
|
||||
|
||||
import abc
|
||||
+import os
|
||||
+import tempfile
|
||||
|
||||
+from contextlib import contextmanager
|
||||
from six import add_metaclass
|
||||
|
||||
from ..errors import FSError
|
||||
@@ -32,6 +35,9 @@ from . import task
|
||||
from . import fstask
|
||||
from . import dfresize
|
||||
|
||||
+import logging
|
||||
+log = logging.getLogger("blivet")
|
||||
+
|
||||
|
||||
@add_metaclass(abc.ABCMeta)
|
||||
class FSResizeTask(fstask.FSTask):
|
||||
@@ -115,6 +121,54 @@ class NTFSResize(FSResize):
|
||||
]
|
||||
|
||||
|
||||
+class XFSResize(FSResize):
|
||||
+ ext = availability.XFSRESIZE_APP
|
||||
+ unit = B
|
||||
+ size_fmt = None
|
||||
+
|
||||
+ @contextmanager
|
||||
+ def _do_temp_mount(self):
|
||||
+ if self.fs.status:
|
||||
+ yield
|
||||
+ else:
|
||||
+ dev_name = os.path.basename(self.fs.device)
|
||||
+ tmpdir = tempfile.mkdtemp(prefix="xfs-tempmount-%s" % dev_name)
|
||||
+ log.debug("mounting XFS on '%s' to '%s' for resize", self.fs.device, tmpdir)
|
||||
+ try:
|
||||
+ self.fs.mount(mountpoint=tmpdir)
|
||||
+ except FSError as e:
|
||||
+ raise FSError("Failed to mount XFS filesystem for resize: %s" % str(e))
|
||||
+
|
||||
+ try:
|
||||
+ yield
|
||||
+ finally:
|
||||
+ util.umount(mountpoint=tmpdir)
|
||||
+ os.rmdir(tmpdir)
|
||||
+
|
||||
+ def _get_block_size(self):
|
||||
+ if self.fs._current_info:
|
||||
+ # this should be set by update_size_info()
|
||||
+ for line in self.fs._current_info.split("\n"):
|
||||
+ if line.startswith("blocksize ="):
|
||||
+ return int(line.split("=")[-1])
|
||||
+
|
||||
+ raise FSError("Failed to get XFS filesystem block size for resize")
|
||||
+
|
||||
+ def size_spec(self):
|
||||
+ # size for xfs_growfs is in blocks
|
||||
+ return str(self.fs.target_size.convert_to(self.unit) / self._get_block_size())
|
||||
+
|
||||
+ @property
|
||||
+ def args(self):
|
||||
+ return [self.fs.system_mountpoint, "-D", self.size_spec()]
|
||||
+
|
||||
+ def do_task(self):
|
||||
+ """ Resizes the XFS format. """
|
||||
+
|
||||
+ with self._do_temp_mount():
|
||||
+ super(XFSResize, self).do_task()
|
||||
+
|
||||
+
|
||||
class TmpFSResize(FSResize):
|
||||
|
||||
ext = availability.MOUNT_APP
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 56d05334231c30699a9c77dedbc23fdb021b9dee Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 14 Jul 2020 11:27:51 +0200
|
||||
Subject: [PATCH 2/4] Add tests for XFS resize
|
||||
|
||||
XFS supports only grow so we can't reuse most of the fstesting
|
||||
code and we also need to test the resize on partition because
|
||||
XFS won't allow grow to size bigger than the underlying block
|
||||
device.
|
||||
---
|
||||
tests/formats_test/fs_test.py | 91 +++++++++++++++++++++++++++++++++
|
||||
tests/formats_test/fstesting.py | 33 ++++++------
|
||||
2 files changed, 107 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/tests/formats_test/fs_test.py b/tests/formats_test/fs_test.py
|
||||
index 15fc0c35..9bc5d20d 100644
|
||||
--- a/tests/formats_test/fs_test.py
|
||||
+++ b/tests/formats_test/fs_test.py
|
||||
@@ -2,8 +2,13 @@ import os
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
+import parted
|
||||
+
|
||||
import blivet.formats.fs as fs
|
||||
from blivet.size import Size, ROUND_DOWN
|
||||
+from blivet.errors import DeviceFormatError
|
||||
+from blivet.formats import get_format
|
||||
+from blivet.devices import PartitionDevice, DiskDevice
|
||||
|
||||
from tests import loopbackedtestcase
|
||||
|
||||
@@ -50,6 +55,92 @@ class ReiserFSTestCase(fstesting.FSAsRoot):
|
||||
class XFSTestCase(fstesting.FSAsRoot):
|
||||
_fs_class = fs.XFS
|
||||
|
||||
+ def can_resize(self, an_fs):
|
||||
+ resize_tasks = (an_fs._resize, an_fs._size_info)
|
||||
+ return not any(t.availability_errors for t in resize_tasks)
|
||||
+
|
||||
+ def _create_partition(self, disk, size):
|
||||
+ disk.format = get_format("disklabel", device=disk.path, label_type="msdos")
|
||||
+ disk.format.create()
|
||||
+ pstart = disk.format.alignment.grainSize
|
||||
+ pend = pstart + int(Size(size) / disk.format.parted_device.sectorSize)
|
||||
+ disk.format.add_partition(pstart, pend, parted.PARTITION_NORMAL)
|
||||
+ disk.format.parted_disk.commit()
|
||||
+ part = disk.format.parted_disk.getPartitionBySector(pstart)
|
||||
+
|
||||
+ device = PartitionDevice(os.path.basename(part.path))
|
||||
+ device.disk = disk
|
||||
+ device.exists = True
|
||||
+ device.parted_partition = part
|
||||
+
|
||||
+ return device
|
||||
+
|
||||
+ def _remove_partition(self, partition, disk):
|
||||
+ disk.format.remove_partition(partition.parted_partition)
|
||||
+ disk.format.parted_disk.commit()
|
||||
+
|
||||
+ def test_resize(self):
|
||||
+ an_fs = self._fs_class()
|
||||
+ if not an_fs.formattable:
|
||||
+ self.skipTest("can not create filesystem %s" % an_fs.name)
|
||||
+ an_fs.device = self.loop_devices[0]
|
||||
+ self.assertIsNone(an_fs.create())
|
||||
+ an_fs.update_size_info()
|
||||
+
|
||||
+ self._test_sizes(an_fs)
|
||||
+ # CHECKME: target size is still 0 after updated_size_info is called.
|
||||
+ self.assertEqual(an_fs.size, Size(0) if an_fs.resizable else an_fs._size)
|
||||
+
|
||||
+ if not self.can_resize(an_fs):
|
||||
+ self.assertFalse(an_fs.resizable)
|
||||
+ # Not resizable, so can not do resizing actions.
|
||||
+ with self.assertRaises(DeviceFormatError):
|
||||
+ an_fs.target_size = Size("64 MiB")
|
||||
+ with self.assertRaises(DeviceFormatError):
|
||||
+ an_fs.do_resize()
|
||||
+ else:
|
||||
+ disk = DiskDevice(os.path.basename(self.loop_devices[0]))
|
||||
+ part = self._create_partition(disk, Size("50 MiB"))
|
||||
+ an_fs = self._fs_class()
|
||||
+ an_fs.device = part.path
|
||||
+ self.assertIsNone(an_fs.create())
|
||||
+ an_fs.update_size_info()
|
||||
+
|
||||
+ self.assertTrue(an_fs.resizable)
|
||||
+
|
||||
+ # grow the partition so we can grow the filesystem
|
||||
+ self._remove_partition(part, disk)
|
||||
+ part = self._create_partition(disk, size=part.size + Size("40 MiB"))
|
||||
+
|
||||
+ # Try a reasonable target size
|
||||
+ TARGET_SIZE = Size("64 MiB")
|
||||
+ an_fs.target_size = TARGET_SIZE
|
||||
+ self.assertEqual(an_fs.target_size, TARGET_SIZE)
|
||||
+ self.assertNotEqual(an_fs._size, TARGET_SIZE)
|
||||
+ self.assertIsNone(an_fs.do_resize())
|
||||
+ ACTUAL_SIZE = TARGET_SIZE.round_to_nearest(an_fs._resize.unit, rounding=ROUND_DOWN)
|
||||
+ self.assertEqual(an_fs.size, ACTUAL_SIZE)
|
||||
+ self.assertEqual(an_fs._size, ACTUAL_SIZE)
|
||||
+ self._test_sizes(an_fs)
|
||||
+
|
||||
+ self._remove_partition(part, disk)
|
||||
+
|
||||
+ # and no errors should occur when checking
|
||||
+ self.assertIsNone(an_fs.do_check())
|
||||
+
|
||||
+ def test_shrink(self):
|
||||
+ self.skipTest("Not checking resize for this test category.")
|
||||
+
|
||||
+ def test_too_small(self):
|
||||
+ self.skipTest("Not checking resize for this test category.")
|
||||
+
|
||||
+ def test_no_explicit_target_size2(self):
|
||||
+ self.skipTest("Not checking resize for this test category.")
|
||||
+
|
||||
+ def test_too_big2(self):
|
||||
+ # XXX this tests assumes that resizing to max size - 1 B will fail, but xfs_grow won't
|
||||
+ self.skipTest("Not checking resize for this test category.")
|
||||
+
|
||||
|
||||
class HFSTestCase(fstesting.FSAsRoot):
|
||||
_fs_class = fs.HFS
|
||||
diff --git a/tests/formats_test/fstesting.py b/tests/formats_test/fstesting.py
|
||||
index 62f806f9..86b2a116 100644
|
||||
--- a/tests/formats_test/fstesting.py
|
||||
+++ b/tests/formats_test/fstesting.py
|
||||
@@ -11,16 +11,6 @@ from blivet.size import Size, ROUND_DOWN
|
||||
from blivet.formats import fs
|
||||
|
||||
|
||||
-def can_resize(an_fs):
|
||||
- """ Returns True if this filesystem has all necessary resizing tools
|
||||
- available.
|
||||
-
|
||||
- :param an_fs: a filesystem object
|
||||
- """
|
||||
- resize_tasks = (an_fs._resize, an_fs._size_info, an_fs._minsize)
|
||||
- return not any(t.availability_errors for t in resize_tasks)
|
||||
-
|
||||
-
|
||||
@add_metaclass(abc.ABCMeta)
|
||||
class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
|
||||
@@ -32,6 +22,15 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
def __init__(self, methodName='run_test'):
|
||||
super(FSAsRoot, self).__init__(methodName=methodName, device_spec=[self._DEVICE_SIZE])
|
||||
|
||||
+ def can_resize(self, an_fs):
|
||||
+ """ Returns True if this filesystem has all necessary resizing tools
|
||||
+ available.
|
||||
+
|
||||
+ :param an_fs: a filesystem object
|
||||
+ """
|
||||
+ resize_tasks = (an_fs._resize, an_fs._size_info, an_fs._minsize)
|
||||
+ return not any(t.availability_errors for t in resize_tasks)
|
||||
+
|
||||
def _test_sizes(self, an_fs):
|
||||
""" Test relationships between different size values.
|
||||
|
||||
@@ -190,7 +189,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
# CHECKME: target size is still 0 after updated_size_info is called.
|
||||
self.assertEqual(an_fs.size, Size(0) if an_fs.resizable else an_fs._size)
|
||||
|
||||
- if not can_resize(an_fs):
|
||||
+ if not self.can_resize(an_fs):
|
||||
self.assertFalse(an_fs.resizable)
|
||||
# Not resizable, so can not do resizing actions.
|
||||
with self.assertRaises(DeviceFormatError):
|
||||
@@ -221,7 +220,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
# in constructor call behavior would be different.
|
||||
|
||||
an_fs = self._fs_class()
|
||||
- if not can_resize(an_fs):
|
||||
+ if not self.can_resize(an_fs):
|
||||
self.skipTest("Not checking resize for this test category.")
|
||||
if not an_fs.formattable:
|
||||
self.skipTest("can not create filesystem %s" % an_fs.name)
|
||||
@@ -244,7 +243,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
"""
|
||||
SIZE = Size("64 MiB")
|
||||
an_fs = self._fs_class(size=SIZE)
|
||||
- if not can_resize(an_fs):
|
||||
+ if not self.can_resize(an_fs):
|
||||
self.skipTest("Not checking resize for this test category.")
|
||||
if not an_fs.formattable:
|
||||
self.skipTest("can not create filesystem %s" % an_fs.name)
|
||||
@@ -264,7 +263,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
|
||||
def test_shrink(self):
|
||||
an_fs = self._fs_class()
|
||||
- if not can_resize(an_fs):
|
||||
+ if not self.can_resize(an_fs):
|
||||
self.skipTest("Not checking resize for this test category.")
|
||||
if not an_fs.formattable:
|
||||
self.skipTest("can not create filesystem %s" % an_fs.name)
|
||||
@@ -296,7 +295,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
|
||||
def test_too_small(self):
|
||||
an_fs = self._fs_class()
|
||||
- if not can_resize(an_fs):
|
||||
+ if not self.can_resize(an_fs):
|
||||
self.skipTest("Not checking resize for this test category.")
|
||||
if not an_fs.formattable:
|
||||
self.skipTest("can not create or resize filesystem %s" % an_fs.name)
|
||||
@@ -315,7 +314,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
|
||||
def test_too_big(self):
|
||||
an_fs = self._fs_class()
|
||||
- if not can_resize(an_fs):
|
||||
+ if not self.can_resize(an_fs):
|
||||
self.skipTest("Not checking resize for this test category.")
|
||||
if not an_fs.formattable:
|
||||
self.skipTest("can not create filesystem %s" % an_fs.name)
|
||||
@@ -334,7 +333,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
||||
|
||||
def test_too_big2(self):
|
||||
an_fs = self._fs_class()
|
||||
- if not can_resize(an_fs):
|
||||
+ if not self.can_resize(an_fs):
|
||||
self.skipTest("Not checking resize for this test category.")
|
||||
if not an_fs.formattable:
|
||||
self.skipTest("can not create filesystem %s" % an_fs.name)
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 51acc04f4639f143b55789a06a68aae988a91296 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Wed, 15 Jul 2020 12:59:04 +0200
|
||||
Subject: [PATCH 3/4] Add support for checking and fixing XFS using xfs_repair
|
||||
|
||||
---
|
||||
blivet/formats/fs.py | 1 +
|
||||
blivet/tasks/availability.py | 1 +
|
||||
blivet/tasks/fsck.py | 12 ++++++++++++
|
||||
tests/formats_test/fs_test.py | 6 +++---
|
||||
4 files changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
|
||||
index 12cb9885..06fbdf10 100644
|
||||
--- a/blivet/formats/fs.py
|
||||
+++ b/blivet/formats/fs.py
|
||||
@@ -1091,6 +1091,7 @@ class XFS(FS):
|
||||
_supported = True
|
||||
_resizable = True
|
||||
_packages = ["xfsprogs"]
|
||||
+ _fsck_class = fsck.XFSCK
|
||||
_info_class = fsinfo.XFSInfo
|
||||
_mkfs_class = fsmkfs.XFSMkfs
|
||||
_readlabel_class = fsreadlabel.XFSReadLabel
|
||||
diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py
|
||||
index df62780c..f3b76650 100644
|
||||
--- a/blivet/tasks/availability.py
|
||||
+++ b/blivet/tasks/availability.py
|
||||
@@ -456,5 +456,6 @@ XFSADMIN_APP = application("xfs_admin")
|
||||
XFSDB_APP = application("xfs_db")
|
||||
XFSFREEZE_APP = application("xfs_freeze")
|
||||
XFSRESIZE_APP = application("xfs_growfs")
|
||||
+XFSREPAIR_APP = application("xfs_repair")
|
||||
|
||||
MOUNT_APP = application("mount")
|
||||
diff --git a/blivet/tasks/fsck.py b/blivet/tasks/fsck.py
|
||||
index 5274f13a..8477f5f8 100644
|
||||
--- a/blivet/tasks/fsck.py
|
||||
+++ b/blivet/tasks/fsck.py
|
||||
@@ -123,6 +123,18 @@ class Ext2FSCK(FSCK):
|
||||
return "\n".join(msgs) or None
|
||||
|
||||
|
||||
+class XFSCK(FSCK):
|
||||
+ _fsck_errors = {1: "Runtime error encountered during repair operation.",
|
||||
+ 2: "XFS repair was unable to proceed due to a dirty log."}
|
||||
+
|
||||
+ ext = availability.XFSREPAIR_APP
|
||||
+ options = []
|
||||
+
|
||||
+ def _error_message(self, rc):
|
||||
+ msgs = (self._fsck_errors[c] for c in self._fsck_errors.keys() if rc & c)
|
||||
+ return "\n".join(msgs) or None
|
||||
+
|
||||
+
|
||||
class HFSPlusFSCK(FSCK):
|
||||
_fsck_errors = {3: "Quick check found a dirty filesystem; no repairs done.",
|
||||
4: "Root filesystem was dirty. System should be rebooted.",
|
||||
diff --git a/tests/formats_test/fs_test.py b/tests/formats_test/fs_test.py
|
||||
index 9bc5d20d..8fb099fd 100644
|
||||
--- a/tests/formats_test/fs_test.py
|
||||
+++ b/tests/formats_test/fs_test.py
|
||||
@@ -123,10 +123,10 @@ class XFSTestCase(fstesting.FSAsRoot):
|
||||
self.assertEqual(an_fs._size, ACTUAL_SIZE)
|
||||
self._test_sizes(an_fs)
|
||||
|
||||
- self._remove_partition(part, disk)
|
||||
+ # and no errors should occur when checking
|
||||
+ self.assertIsNone(an_fs.do_check())
|
||||
|
||||
- # and no errors should occur when checking
|
||||
- self.assertIsNone(an_fs.do_check())
|
||||
+ self._remove_partition(part, disk)
|
||||
|
||||
def test_shrink(self):
|
||||
self.skipTest("Not checking resize for this test category.")
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 2a6947098e66f880193f3bac2282a6c7857ca5f7 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Thu, 16 Jul 2020 09:05:35 +0200
|
||||
Subject: [PATCH 4/4] Use xfs_db in read-only mode when getting XFS information
|
||||
|
||||
This way it will also work on mounted filesystems.
|
||||
---
|
||||
blivet/tasks/fsinfo.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/blivet/tasks/fsinfo.py b/blivet/tasks/fsinfo.py
|
||||
index af208f5d..41ff700f 100644
|
||||
--- a/blivet/tasks/fsinfo.py
|
||||
+++ b/blivet/tasks/fsinfo.py
|
||||
@@ -95,7 +95,7 @@ class ReiserFSInfo(FSInfo):
|
||||
|
||||
class XFSInfo(FSInfo):
|
||||
ext = availability.XFSDB_APP
|
||||
- options = ["-c", "sb 0", "-c", "p dblocks", "-c", "p blocksize"]
|
||||
+ options = ["-c", "sb 0", "-c", "p dblocks", "-c", "p blocksize", "-r"]
|
||||
|
||||
|
||||
class UnimplementedFSInfo(fstask.UnimplementedFSTask):
|
||||
--
|
||||
2.26.2
|
||||
|
76
SOURCES/0013-Do-not-limit-swap-to-128-GiB.patch
Normal file
76
SOURCES/0013-Do-not-limit-swap-to-128-GiB.patch
Normal file
@ -0,0 +1,76 @@
|
||||
From aa4ce218fe9b4ee3571d872ff1575a499596181c Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Fri, 29 May 2020 12:14:30 +0200
|
||||
Subject: [PATCH 1/2] Do not limit swap to 128 GiB
|
||||
|
||||
The limit was part of change to limit suggested swap size in
|
||||
kickstart which doesn't use the SwapSpace._max_size so there is no
|
||||
reason to limit this for manual installations.
|
||||
16 TiB seems to be max usable swap size based on mkswap code.
|
||||
|
||||
Resolves: rhbz#1656485
|
||||
---
|
||||
blivet/formats/swap.py | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/blivet/formats/swap.py b/blivet/formats/swap.py
|
||||
index 4b8a7edf..3cc59138 100644
|
||||
--- a/blivet/formats/swap.py
|
||||
+++ b/blivet/formats/swap.py
|
||||
@@ -52,8 +52,7 @@ class SwapSpace(DeviceFormat):
|
||||
_linux_native = True # for clearpart
|
||||
_plugin = availability.BLOCKDEV_SWAP_PLUGIN
|
||||
|
||||
- # see rhbz#744129 for details
|
||||
- _max_size = Size("128 GiB")
|
||||
+ _max_size = Size("16 TiB")
|
||||
|
||||
config_actions_map = {"label": "write_label"}
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 93aa6ad87116f1c86616d73dbe561251c4a0c286 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Thu, 11 Jun 2020 14:27:44 +0200
|
||||
Subject: [PATCH 2/2] Add test for SwapSpace max size
|
||||
|
||||
---
|
||||
tests/formats_test/swap_test.py | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
create mode 100644 tests/formats_test/swap_test.py
|
||||
|
||||
diff --git a/tests/formats_test/swap_test.py b/tests/formats_test/swap_test.py
|
||||
new file mode 100644
|
||||
index 00000000..56356144
|
||||
--- /dev/null
|
||||
+++ b/tests/formats_test/swap_test.py
|
||||
@@ -0,0 +1,24 @@
|
||||
+import test_compat # pylint: disable=unused-import
|
||||
+
|
||||
+import six
|
||||
+import unittest
|
||||
+
|
||||
+from blivet.devices.storage import StorageDevice
|
||||
+from blivet.errors import DeviceError
|
||||
+from blivet.formats import get_format
|
||||
+
|
||||
+from blivet.size import Size
|
||||
+
|
||||
+
|
||||
+class SwapNodevTestCase(unittest.TestCase):
|
||||
+
|
||||
+ def test_swap_max_size(self):
|
||||
+ StorageDevice("dev", size=Size("129 GiB"),
|
||||
+ fmt=get_format("swap"))
|
||||
+
|
||||
+ StorageDevice("dev", size=Size("15 TiB"),
|
||||
+ fmt=get_format("swap"))
|
||||
+
|
||||
+ with six.assertRaisesRegex(self, DeviceError, "device is too large for new format"):
|
||||
+ StorageDevice("dev", size=Size("17 TiB"),
|
||||
+ fmt=get_format("swap"))
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,78 @@
|
||||
From 4e6a322d32d2a12f8a87ab763a6286cf3d7b5c27 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 8 Sep 2020 13:57:40 +0200
|
||||
Subject: [PATCH] Use UnusableConfigurationError for partially hidden multipath
|
||||
devices
|
||||
|
||||
Follow-up for https://github.com/storaged-project/blivet/pull/883
|
||||
to make Anaconda show an error message instead of crashing.
|
||||
|
||||
Resolves: rhbz#1877052
|
||||
---
|
||||
blivet/devicetree.py | 4 ++--
|
||||
blivet/errors.py | 6 ++++++
|
||||
tests/devicetree_test.py | 4 ++--
|
||||
3 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
|
||||
index 2afb0d0e..57a9bbd7 100644
|
||||
--- a/blivet/devicetree.py
|
||||
+++ b/blivet/devicetree.py
|
||||
@@ -32,7 +32,7 @@ from gi.repository import BlockDev as blockdev
|
||||
|
||||
from .actionlist import ActionList
|
||||
from .callbacks import callbacks
|
||||
-from .errors import DeviceError, DeviceTreeError, StorageError, DuplicateUUIDError
|
||||
+from .errors import DeviceError, DeviceTreeError, StorageError, DuplicateUUIDError, InvalidMultideviceSelection
|
||||
from .deviceaction import ActionDestroyDevice, ActionDestroyFormat
|
||||
from .devices import BTRFSDevice, NoDevice, PartitionDevice
|
||||
from .devices import LVMLogicalVolumeDevice, LVMVolumeGroupDevice
|
||||
@@ -936,7 +936,7 @@ class DeviceTreeBase(object):
|
||||
if is_ignored:
|
||||
if len(disk.children) == 1:
|
||||
if not all(self._is_ignored_disk(d) for d in disk.children[0].parents):
|
||||
- raise DeviceTreeError("Including only a subset of raid/multipath member disks is not allowed.")
|
||||
+ raise InvalidMultideviceSelection("Including only a subset of raid/multipath member disks is not allowed.")
|
||||
|
||||
# and also children like fwraid or mpath
|
||||
self.hide(disk.children[0])
|
||||
diff --git a/blivet/errors.py b/blivet/errors.py
|
||||
index 811abf81..7a93f1ce 100644
|
||||
--- a/blivet/errors.py
|
||||
+++ b/blivet/errors.py
|
||||
@@ -233,6 +233,12 @@ class DuplicateVGError(UnusableConfigurationError):
|
||||
"Hint 2: You can get the VG UUIDs by running "
|
||||
"'pvs -o +vg_uuid'.")
|
||||
|
||||
+
|
||||
+class InvalidMultideviceSelection(UnusableConfigurationError):
|
||||
+ suggestion = N_("All parent devices must be selected when choosing exclusive "
|
||||
+ "or ignored disks for a multipath or firmware RAID device.")
|
||||
+
|
||||
+
|
||||
# DeviceAction
|
||||
|
||||
|
||||
diff --git a/tests/devicetree_test.py b/tests/devicetree_test.py
|
||||
index 6032e7f6..4e47ffc3 100644
|
||||
--- a/tests/devicetree_test.py
|
||||
+++ b/tests/devicetree_test.py
|
||||
@@ -5,7 +5,7 @@ import six
|
||||
import unittest
|
||||
|
||||
from blivet.actionlist import ActionList
|
||||
-from blivet.errors import DeviceTreeError, DuplicateUUIDError
|
||||
+from blivet.errors import DeviceTreeError, DuplicateUUIDError, InvalidMultideviceSelection
|
||||
from blivet.deviceaction import ACTION_TYPE_DESTROY, ACTION_OBJECT_DEVICE
|
||||
from blivet.devicelibs import lvm
|
||||
from blivet.devices import DiskDevice
|
||||
@@ -512,5 +512,5 @@ class DeviceTreeIgnoredExclusiveMultipathTestCase(unittest.TestCase):
|
||||
self.tree.ignored_disks = ["sda", "sdb"]
|
||||
self.tree.exclusive_disks = []
|
||||
|
||||
- with self.assertRaises(DeviceTreeError):
|
||||
+ with self.assertRaises(InvalidMultideviceSelection):
|
||||
self.tree._hide_ignored_disks()
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,32 @@
|
||||
From 866a48e6c3d8246d2897bb402a191df5f2848aa4 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 10:33:33 +0200
|
||||
Subject: [PATCH] Fix possible UnicodeDecodeError when reading model from sysfs
|
||||
|
||||
Some Innovation IT NVMe devices have an (invalid) unicode in their
|
||||
model name.
|
||||
|
||||
Resolves: rhbz#1849326
|
||||
---
|
||||
blivet/udev.py | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/blivet/udev.py b/blivet/udev.py
|
||||
index 41c99496..2c795225 100644
|
||||
--- a/blivet/udev.py
|
||||
+++ b/blivet/udev.py
|
||||
@@ -185,8 +185,9 @@ def __is_blacklisted_blockdev(dev_name):
|
||||
if any(re.search(expr, dev_name) for expr in device_name_blacklist):
|
||||
return True
|
||||
|
||||
- if os.path.exists("/sys/class/block/%s/device/model" % (dev_name,)):
|
||||
- model = open("/sys/class/block/%s/device/model" % (dev_name,)).read()
|
||||
+ model_path = "/sys/class/block/%s/device/model" % dev_name
|
||||
+ if os.path.exists(model_path):
|
||||
+ model = open(model_path, encoding="utf-8", errors="replace").read()
|
||||
for bad in ("IBM *STMF KERNEL", "SCEI Flash-5", "DGC LUNZ"):
|
||||
if model.find(bad) != -1:
|
||||
log.info("ignoring %s with model %s", dev_name, model)
|
||||
--
|
||||
2.26.2
|
||||
|
415
SOURCES/0016-Basic-LVM-VDO-support.patch
Normal file
415
SOURCES/0016-Basic-LVM-VDO-support.patch
Normal file
@ -0,0 +1,415 @@
|
||||
From 3f6bbf52442609b8e6e3919a3fdd8c5af64923e6 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 12 May 2020 12:48:41 +0200
|
||||
Subject: [PATCH 1/3] Add basic support for LVM VDO devices
|
||||
|
||||
This adds support for LVM VDO devices detection during populate
|
||||
and allows removing both VDO LVs and VDO pools using actions.
|
||||
---
|
||||
blivet/devices/lvm.py | 150 +++++++++++++++++++++++++++++++-
|
||||
blivet/populator/helpers/lvm.py | 16 +++-
|
||||
tests/action_test.py | 39 +++++++++
|
||||
tests/devices_test/lvm_test.py | 34 ++++++++
|
||||
tests/storagetestcase.py | 11 ++-
|
||||
5 files changed, 245 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
|
||||
index 97de6acd..d9e24a33 100644
|
||||
--- a/blivet/devices/lvm.py
|
||||
+++ b/blivet/devices/lvm.py
|
||||
@@ -1789,8 +1789,132 @@ class LVMThinLogicalVolumeMixin(object):
|
||||
data.pool_name = self.pool.lvname
|
||||
|
||||
|
||||
+class LVMVDOPoolMixin(object):
|
||||
+ def __init__(self):
|
||||
+ self._lvs = []
|
||||
+
|
||||
+ @property
|
||||
+ def is_vdo_pool(self):
|
||||
+ return self.seg_type == "vdo-pool"
|
||||
+
|
||||
+ @property
|
||||
+ def type(self):
|
||||
+ return "lvmvdopool"
|
||||
+
|
||||
+ @property
|
||||
+ def resizable(self):
|
||||
+ return False
|
||||
+
|
||||
+ @util.requires_property("is_vdo_pool")
|
||||
+ def _add_log_vol(self, lv):
|
||||
+ """ Add an LV to this VDO pool. """
|
||||
+ if lv in self._lvs:
|
||||
+ raise ValueError("lv is already part of this VDO pool")
|
||||
+
|
||||
+ self.vg._add_log_vol(lv)
|
||||
+ log.debug("Adding %s/%s to %s", lv.name, lv.size, self.name)
|
||||
+ self._lvs.append(lv)
|
||||
+
|
||||
+ @util.requires_property("is_vdo_pool")
|
||||
+ def _remove_log_vol(self, lv):
|
||||
+ """ Remove an LV from this VDO pool. """
|
||||
+ if lv not in self._lvs:
|
||||
+ raise ValueError("specified lv is not part of this VDO pool")
|
||||
+
|
||||
+ self._lvs.remove(lv)
|
||||
+ self.vg._remove_log_vol(lv)
|
||||
+
|
||||
+ @property
|
||||
+ @util.requires_property("is_vdo_pool")
|
||||
+ def lvs(self):
|
||||
+ """ A list of this VDO pool's LVs """
|
||||
+ return self._lvs[:] # we don't want folks changing our list
|
||||
+
|
||||
+ @property
|
||||
+ def direct(self):
|
||||
+ """ Is this device directly accessible? """
|
||||
+ return False
|
||||
+
|
||||
+ def _create(self):
|
||||
+ """ Create the device. """
|
||||
+ raise NotImplementedError
|
||||
+
|
||||
+
|
||||
+class LVMVDOLogicalVolumeMixin(object):
|
||||
+ def __init__(self):
|
||||
+ pass
|
||||
+
|
||||
+ def _init_check(self):
|
||||
+ pass
|
||||
+
|
||||
+ def _check_parents(self):
|
||||
+ """Check that this device has parents as expected"""
|
||||
+ if isinstance(self.parents, (list, ParentList)):
|
||||
+ if len(self.parents) != 1:
|
||||
+ raise ValueError("constructor requires a single vdo-pool LV")
|
||||
+
|
||||
+ container = self.parents[0]
|
||||
+ else:
|
||||
+ container = self.parents
|
||||
+
|
||||
+ if not container or not isinstance(container, LVMLogicalVolumeDevice) or not container.is_vdo_pool:
|
||||
+ raise ValueError("constructor requires a vdo-pool LV")
|
||||
+
|
||||
+ @property
|
||||
+ def vg_space_used(self):
|
||||
+ return Size(0) # the pool's size is already accounted for in the vg
|
||||
+
|
||||
+ @property
|
||||
+ def is_vdo_lv(self):
|
||||
+ return self.seg_type == "vdo"
|
||||
+
|
||||
+ @property
|
||||
+ def vg(self):
|
||||
+ # parents[0] is the pool, not the VG so set the VG here
|
||||
+ return self.pool.vg
|
||||
+
|
||||
+ @property
|
||||
+ def type(self):
|
||||
+ return "vdolv"
|
||||
+
|
||||
+ @property
|
||||
+ def resizable(self):
|
||||
+ return False
|
||||
+
|
||||
+ @property
|
||||
+ @util.requires_property("is_vdo_lv")
|
||||
+ def pool(self):
|
||||
+ return self.parents[0]
|
||||
+
|
||||
+ def _create(self):
|
||||
+ """ Create the device. """
|
||||
+ raise NotImplementedError
|
||||
+
|
||||
+ def _destroy(self):
|
||||
+ # nothing to do here, VDO LV is destroyed automatically together with
|
||||
+ # the VDO pool
|
||||
+ pass
|
||||
+
|
||||
+ def remove_hook(self, modparent=True):
|
||||
+ if modparent:
|
||||
+ self.pool._remove_log_vol(self)
|
||||
+
|
||||
+ # pylint: disable=bad-super-call
|
||||
+ super(LVMLogicalVolumeBase, self).remove_hook(modparent=modparent)
|
||||
+
|
||||
+ def add_hook(self, new=True):
|
||||
+ # pylint: disable=bad-super-call
|
||||
+ super(LVMLogicalVolumeBase, self).add_hook(new=new)
|
||||
+ if new:
|
||||
+ return
|
||||
+
|
||||
+ if self not in self.pool.lvs:
|
||||
+ self.pool._add_log_vol(self)
|
||||
+
|
||||
+
|
||||
class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin, LVMSnapshotMixin,
|
||||
- LVMThinPoolMixin, LVMThinLogicalVolumeMixin):
|
||||
+ LVMThinPoolMixin, LVMThinLogicalVolumeMixin, LVMVDOPoolMixin,
|
||||
+ LVMVDOLogicalVolumeMixin):
|
||||
""" An LVM Logical Volume """
|
||||
|
||||
# generally resizable, see :property:`resizable` for details
|
||||
@@ -1879,6 +2003,8 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
|
||||
LVMLogicalVolumeBase.__init__(self, name, parents, size, uuid, seg_type,
|
||||
fmt, exists, sysfs_path, grow, maxsize,
|
||||
percent, cache_request, pvs, from_lvs)
|
||||
+ LVMVDOPoolMixin.__init__(self)
|
||||
+ LVMVDOLogicalVolumeMixin.__init__(self)
|
||||
|
||||
LVMInternalLogicalVolumeMixin._init_check(self)
|
||||
LVMSnapshotMixin._init_check(self)
|
||||
@@ -1905,6 +2031,10 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
|
||||
ret.append(LVMThinPoolMixin)
|
||||
if self.is_thin_lv:
|
||||
ret.append(LVMThinLogicalVolumeMixin)
|
||||
+ if self.is_vdo_pool:
|
||||
+ ret.append(LVMVDOPoolMixin)
|
||||
+ if self.is_vdo_lv:
|
||||
+ ret.append(LVMVDOLogicalVolumeMixin)
|
||||
return ret
|
||||
|
||||
def _try_specific_call(self, name, *args, **kwargs):
|
||||
@@ -2066,6 +2196,11 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
|
||||
def display_lv_name(self):
|
||||
return self.lvname
|
||||
|
||||
+ @property
|
||||
+ @type_specific
|
||||
+ def pool(self):
|
||||
+ return super(LVMLogicalVolumeDevice, self).pool
|
||||
+
|
||||
def _setup(self, orig=False):
|
||||
""" Open, or set up, a device. """
|
||||
log_method_call(self, self.name, orig=orig, status=self.status,
|
||||
@@ -2167,6 +2302,19 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
|
||||
udev.settle()
|
||||
blockdev.lvm.lvresize(self.vg.name, self._name, self.size)
|
||||
|
||||
+ @type_specific
|
||||
+ def _add_log_vol(self, lv):
|
||||
+ pass
|
||||
+
|
||||
+ @type_specific
|
||||
+ def _remove_log_vol(self, lv):
|
||||
+ pass
|
||||
+
|
||||
+ @property
|
||||
+ @type_specific
|
||||
+ def lvs(self):
|
||||
+ return []
|
||||
+
|
||||
@property
|
||||
@type_specific
|
||||
def direct(self):
|
||||
diff --git a/blivet/populator/helpers/lvm.py b/blivet/populator/helpers/lvm.py
|
||||
index 4b674fac..ff8bf59f 100644
|
||||
--- a/blivet/populator/helpers/lvm.py
|
||||
+++ b/blivet/populator/helpers/lvm.py
|
||||
@@ -211,9 +211,6 @@ class LVMFormatPopulator(FormatPopulator):
|
||||
origin = self._devicetree.get_device_by_name(origin_device_name)
|
||||
|
||||
lv_kwargs["origin"] = origin
|
||||
- elif lv_attr[0] == 'v':
|
||||
- # skip vorigins
|
||||
- return
|
||||
elif lv_attr[0] in 'IrielTCo' and lv_name.endswith(']'):
|
||||
# an internal LV, add the an instance of the appropriate class
|
||||
# to internal_lvs for later processing when non-internal LVs are
|
||||
@@ -237,6 +234,19 @@ class LVMFormatPopulator(FormatPopulator):
|
||||
origin = self._devicetree.get_device_by_name(origin_device_name)
|
||||
lv_kwargs["origin"] = origin
|
||||
|
||||
+ lv_parents = [self._devicetree.get_device_by_name(pool_device_name)]
|
||||
+ elif lv_attr[0] == 'd':
|
||||
+ # vdo pool
|
||||
+ # nothing to do here
|
||||
+ pass
|
||||
+ elif lv_attr[0] == 'v':
|
||||
+ if lv_type != "vdo":
|
||||
+ # skip vorigins
|
||||
+ return
|
||||
+ pool_name = blockdev.lvm.vdolvpoolname(vg_name, lv_name)
|
||||
+ pool_device_name = "%s-%s" % (vg_name, pool_name)
|
||||
+ add_required_lv(pool_device_name, "failed to look up VDO pool")
|
||||
+
|
||||
lv_parents = [self._devicetree.get_device_by_name(pool_device_name)]
|
||||
elif lv_name.endswith(']'):
|
||||
# unrecognized Internal LVM2 device
|
||||
diff --git a/tests/action_test.py b/tests/action_test.py
|
||||
index 90c1b312..8f9a7424 100644
|
||||
--- a/tests/action_test.py
|
||||
+++ b/tests/action_test.py
|
||||
@@ -1252,6 +1252,45 @@ class DeviceActionTestCase(StorageTestCase):
|
||||
self.assertEqual(set(self.storage.lvs), {pool})
|
||||
self.assertEqual(set(pool._internal_lvs), {lv1, lv2})
|
||||
|
||||
+ def test_lvm_vdo_destroy(self):
|
||||
+ self.destroy_all_devices()
|
||||
+ sdc = self.storage.devicetree.get_device_by_name("sdc")
|
||||
+ sdc1 = self.new_device(device_class=PartitionDevice, name="sdc1",
|
||||
+ size=Size("50 GiB"), parents=[sdc],
|
||||
+ fmt=blivet.formats.get_format("lvmpv"))
|
||||
+ self.schedule_create_device(sdc1)
|
||||
+
|
||||
+ vg = self.new_device(device_class=LVMVolumeGroupDevice,
|
||||
+ name="vg", parents=[sdc1])
|
||||
+ self.schedule_create_device(vg)
|
||||
+
|
||||
+ pool = self.new_device(device_class=LVMLogicalVolumeDevice,
|
||||
+ name="data", parents=[vg],
|
||||
+ size=Size("10 GiB"),
|
||||
+ seg_type="vdo-pool", exists=True)
|
||||
+ self.storage.devicetree._add_device(pool)
|
||||
+ lv = self.new_device(device_class=LVMLogicalVolumeDevice,
|
||||
+ name="meta", parents=[pool],
|
||||
+ size=Size("50 GiB"),
|
||||
+ seg_type="vdo", exists=True)
|
||||
+ self.storage.devicetree._add_device(lv)
|
||||
+
|
||||
+ remove_lv = self.schedule_destroy_device(lv)
|
||||
+ self.assertListEqual(pool.lvs, [])
|
||||
+ self.assertNotIn(lv, vg.lvs)
|
||||
+
|
||||
+ # cancelling the action should put lv back to both vg and pool lvs
|
||||
+ self.storage.devicetree.actions.remove(remove_lv)
|
||||
+ self.assertListEqual(pool.lvs, [lv])
|
||||
+ self.assertIn(lv, vg.lvs)
|
||||
+
|
||||
+ # can't remove non-leaf pool
|
||||
+ with self.assertRaises(ValueError):
|
||||
+ self.schedule_destroy_device(pool)
|
||||
+
|
||||
+ self.schedule_destroy_device(lv)
|
||||
+ self.schedule_destroy_device(pool)
|
||||
+
|
||||
|
||||
class ConfigurationActionsTest(unittest.TestCase):
|
||||
|
||||
diff --git a/tests/devices_test/lvm_test.py b/tests/devices_test/lvm_test.py
|
||||
index 9e701d18..204cb99a 100644
|
||||
--- a/tests/devices_test/lvm_test.py
|
||||
+++ b/tests/devices_test/lvm_test.py
|
||||
@@ -405,6 +405,40 @@ class LVMDeviceTest(unittest.TestCase):
|
||||
exists=False)
|
||||
self.assertFalse(vg.is_empty)
|
||||
|
||||
+ def test_lvm_vdo_pool(self):
|
||||
+ pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
|
||||
+ size=Size("1 GiB"), exists=True)
|
||||
+ vg = LVMVolumeGroupDevice("testvg", parents=[pv])
|
||||
+ pool = LVMLogicalVolumeDevice("testpool", parents=[vg], size=Size("512 MiB"),
|
||||
+ seg_type="vdo-pool", exists=True)
|
||||
+ self.assertTrue(pool.is_vdo_pool)
|
||||
+
|
||||
+ free = vg.free_space
|
||||
+ lv = LVMLogicalVolumeDevice("testlv", parents=[pool], size=Size("2 GiB"),
|
||||
+ seg_type="vdo", exists=True)
|
||||
+ self.assertTrue(lv.is_vdo_lv)
|
||||
+ self.assertEqual(lv.vg, vg)
|
||||
+ self.assertEqual(lv.pool, pool)
|
||||
+
|
||||
+ # free space in the vg shouldn't be affected by the vdo lv
|
||||
+ self.assertEqual(lv.vg_space_used, 0)
|
||||
+ self.assertEqual(free, vg.free_space)
|
||||
+
|
||||
+ self.assertListEqual(pool.lvs, [lv])
|
||||
+
|
||||
+ # now try to destroy both the pool and the vdo lv
|
||||
+ # for the lv this should be a no-op, destroying the pool should destroy both
|
||||
+ with patch("blivet.devices.lvm.blockdev.lvm") as lvm:
|
||||
+ lv.destroy()
|
||||
+ lv.remove_hook()
|
||||
+ self.assertFalse(lv.exists)
|
||||
+ self.assertFalse(lvm.lvremove.called)
|
||||
+ self.assertListEqual(pool.lvs, [])
|
||||
+
|
||||
+ pool.destroy()
|
||||
+ self.assertFalse(pool.exists)
|
||||
+ self.assertTrue(lvm.lvremove.called)
|
||||
+
|
||||
|
||||
class TypeSpecificCallsTest(unittest.TestCase):
|
||||
def test_type_specific_calls(self):
|
||||
diff --git a/tests/storagetestcase.py b/tests/storagetestcase.py
|
||||
index e581bca6..1844dec5 100644
|
||||
--- a/tests/storagetestcase.py
|
||||
+++ b/tests/storagetestcase.py
|
||||
@@ -96,7 +96,16 @@ class StorageTestCase(unittest.TestCase):
|
||||
def new_device(self, *args, **kwargs):
|
||||
""" Return a new Device instance suitable for testing. """
|
||||
device_class = kwargs.pop("device_class")
|
||||
- exists = kwargs.pop("exists", False)
|
||||
+
|
||||
+ # we intentionally don't pass the "exists" kwarg to the constructor
|
||||
+ # becauses this causes issues with some devices (especially partitions)
|
||||
+ # but we still need it for some LVs like VDO because we can't create
|
||||
+ # those so we need to fake their existence even for the constructor
|
||||
+ if device_class is blivet.devices.LVMLogicalVolumeDevice:
|
||||
+ exists = kwargs.get("exists", False)
|
||||
+ else:
|
||||
+ exists = kwargs.pop("exists", False)
|
||||
+
|
||||
part_type = kwargs.pop("part_type", parted.PARTITION_NORMAL)
|
||||
device = device_class(*args, **kwargs)
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From f05a66e1bed1ca1f3cd7d7ffecd6693ab4d7f32a Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 12 May 2020 12:52:47 +0200
|
||||
Subject: [PATCH 2/3] Fix checking for filesystem support in action_test
|
||||
|
||||
---
|
||||
tests/action_test.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/action_test.py b/tests/action_test.py
|
||||
index 8f9a7424..228eb97a 100644
|
||||
--- a/tests/action_test.py
|
||||
+++ b/tests/action_test.py
|
||||
@@ -56,7 +56,7 @@ FORMAT_CLASSES = [
|
||||
|
||||
|
||||
@unittest.skipUnless(not any(x.unavailable_type_dependencies() for x in DEVICE_CLASSES), "some unsupported device classes required for this test")
|
||||
-@unittest.skipUnless(not any(x().utils_available for x in FORMAT_CLASSES), "some unsupported format classes required for this test")
|
||||
+@unittest.skipUnless(all(x().utils_available for x in FORMAT_CLASSES), "some unsupported format classes required for this test")
|
||||
class DeviceActionTestCase(StorageTestCase):
|
||||
|
||||
""" DeviceActionTestSuite """
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 69bd2e69e21c8779377a6f54b3d83cb35138867a Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 12 May 2020 12:54:03 +0200
|
||||
Subject: [PATCH 3/3] Fix LV min size for resize in test_action_dependencies
|
||||
|
||||
We've recently changed min size for all filesystems so we can't
|
||||
resize the LV to the device minimal size.
|
||||
This was overlooked in the original change because these tests
|
||||
were skipped.
|
||||
---
|
||||
tests/action_test.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/action_test.py b/tests/action_test.py
|
||||
index 228eb97a..77176f46 100644
|
||||
--- a/tests/action_test.py
|
||||
+++ b/tests/action_test.py
|
||||
@@ -870,7 +870,7 @@ class DeviceActionTestCase(StorageTestCase):
|
||||
name="testlv2", parents=[testvg])
|
||||
testlv2.format = self.new_format("ext4", device=testlv2.path,
|
||||
exists=True, device_instance=testlv2)
|
||||
- shrink_lv2 = ActionResizeDevice(testlv2, testlv2.size - Size("10 GiB"))
|
||||
+ shrink_lv2 = ActionResizeDevice(testlv2, testlv2.size - Size("10 GiB") + Ext4FS._min_size)
|
||||
shrink_lv2.apply()
|
||||
|
||||
self.assertTrue(grow_lv.requires(shrink_lv2))
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,30 @@
|
||||
From d477f8d076789cbe1c0a85545ea8b5133fdc4bdf Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Fri, 18 Sep 2020 13:58:48 +0200
|
||||
Subject: [PATCH] Let parted fix fixable issues with partition table
|
||||
|
||||
This will automatically fix issues like GPT partition table not
|
||||
covering whole device after disk size change.
|
||||
|
||||
Resolves: rhbz#1846869
|
||||
---
|
||||
blivet/populator/populator.py | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/blivet/populator/populator.py b/blivet/populator/populator.py
|
||||
index 465c272d..fe566816 100644
|
||||
--- a/blivet/populator/populator.py
|
||||
+++ b/blivet/populator/populator.py
|
||||
@@ -64,6 +64,9 @@ def parted_exn_handler(exn_type, exn_options, exn_msg):
|
||||
if exn_type == parted.EXCEPTION_TYPE_ERROR and \
|
||||
exn_options == parted.EXCEPTION_OPT_YES_NO:
|
||||
ret = parted.EXCEPTION_RESOLVE_YES
|
||||
+ elif exn_type == parted.EXCEPTION_TYPE_WARNING and \
|
||||
+ exn_options & parted.EXCEPTION_RESOLVE_FIX:
|
||||
+ ret = parted.EXCEPTION_RESOLVE_FIX
|
||||
return ret
|
||||
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,112 @@
|
||||
From 430cd2cdba8fba434b5bed2d2a7ed97803c62f6d Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 5 Jan 2021 16:56:52 +0100
|
||||
Subject: [PATCH 1/3] Fix possible UnicodeDecodeError when reading sysfs
|
||||
attributes
|
||||
|
||||
This is a follow-up for https://github.com/storaged-project/blivet/pull/861
|
||||
where we fixed reading device model in "__is_blacklisted_blockdev"
|
||||
but we read the device model from other places too so it makes
|
||||
more sense to "fix" all sysfs attribute reads.
|
||||
---
|
||||
blivet/util.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/blivet/util.py b/blivet/util.py
|
||||
index 2fa9c8fc..48b7818f 100644
|
||||
--- a/blivet/util.py
|
||||
+++ b/blivet/util.py
|
||||
@@ -379,7 +379,7 @@ def get_sysfs_attr(path, attr, root=None):
|
||||
log.warning("%s is not a valid attribute", attr)
|
||||
return None
|
||||
|
||||
- f = open(fullattr, "r")
|
||||
+ f = open(fullattr, "r", encoding="utf-8", errors="replace")
|
||||
data = f.read()
|
||||
f.close()
|
||||
sdata = "".join(["%02x" % (ord(x),) for x in data])
|
||||
--
|
||||
2.29.2
|
||||
|
||||
|
||||
From 15350b52f30910d4fadad92da0195710adcb69a0 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 5 Jan 2021 16:59:14 +0100
|
||||
Subject: [PATCH 2/3] Use util.get_sysfs_attr in __is_ignored_blockdev to read
|
||||
device mode
|
||||
|
||||
---
|
||||
blivet/udev.py | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/blivet/udev.py b/blivet/udev.py
|
||||
index 2c795225..25375459 100644
|
||||
--- a/blivet/udev.py
|
||||
+++ b/blivet/udev.py
|
||||
@@ -185,9 +185,8 @@ def __is_blacklisted_blockdev(dev_name):
|
||||
if any(re.search(expr, dev_name) for expr in device_name_blacklist):
|
||||
return True
|
||||
|
||||
- model_path = "/sys/class/block/%s/device/model" % dev_name
|
||||
- if os.path.exists(model_path):
|
||||
- model = open(model_path, encoding="utf-8", errors="replace").read()
|
||||
+ model = util.get_sysfs_attr("/sys/class/block/%s" % dev_name, "device/model")
|
||||
+ if model:
|
||||
for bad in ("IBM *STMF KERNEL", "SCEI Flash-5", "DGC LUNZ"):
|
||||
if model.find(bad) != -1:
|
||||
log.info("ignoring %s with model %s", dev_name, model)
|
||||
--
|
||||
2.29.2
|
||||
|
||||
|
||||
From 64ece8c0dafb550bbde4798a766515fb04f44568 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Wed, 6 Jan 2021 12:34:49 +0100
|
||||
Subject: [PATCH 3/3] Add test for util.get_sysfs_attr
|
||||
|
||||
---
|
||||
tests/util_test.py | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/tests/util_test.py b/tests/util_test.py
|
||||
index 9a2ff492..853b6166 100644
|
||||
--- a/tests/util_test.py
|
||||
+++ b/tests/util_test.py
|
||||
@@ -2,7 +2,9 @@
|
||||
import test_compat
|
||||
|
||||
from six.moves import mock
|
||||
+import os
|
||||
import six
|
||||
+import tempfile
|
||||
import unittest
|
||||
from decimal import Decimal
|
||||
|
||||
@@ -157,3 +159,24 @@ class DependencyGuardTestCase(unittest.TestCase):
|
||||
with mock.patch.object(_requires_something, '_check_avail', return_value=True):
|
||||
self.assertEqual(self._test_dependency_guard_non_critical(), True)
|
||||
self.assertEqual(self._test_dependency_guard_critical(), True)
|
||||
+
|
||||
+
|
||||
+class GetSysfsAttrTestCase(unittest.TestCase):
|
||||
+
|
||||
+ def test_get_sysfs_attr(self):
|
||||
+
|
||||
+ with tempfile.TemporaryDirectory() as sysfs:
|
||||
+ model_file = os.path.join(sysfs, "model")
|
||||
+ with open(model_file, "w") as f:
|
||||
+ f.write("test model\n")
|
||||
+
|
||||
+ model = util.get_sysfs_attr(sysfs, "model")
|
||||
+ self.assertEqual(model, "test model")
|
||||
+
|
||||
+ # now with some invalid byte in the model
|
||||
+ with open(model_file, "wb") as f:
|
||||
+ f.write(b"test model\xef\n")
|
||||
+
|
||||
+ # the unicode replacement character (U+FFFD) should be used instead
|
||||
+ model = util.get_sysfs_attr(sysfs, "model")
|
||||
+ self.assertEqual(model, "test model\ufffd")
|
||||
--
|
||||
2.29.2
|
||||
|
2027
SOURCES/0019-LVM-VDO-support.patch
Normal file
2027
SOURCES/0019-LVM-VDO-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,83 @@
|
||||
From dabc5f8a29f34aebd9ea61405d822b5d5bef1ec2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
|
||||
Date: Tue, 2 Mar 2021 14:13:29 +0100
|
||||
Subject: [PATCH] apply directory's SELinux context to freshly created mount
|
||||
points
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
|
||||
|
||||
Resolves: rhbz#1934076
|
||||
---
|
||||
blivet/formats/fs.py | 3 ++-
|
||||
blivet/util.py | 9 +++++----
|
||||
2 files changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
|
||||
index e61e5b86..a92d3485 100644
|
||||
--- a/blivet/formats/fs.py
|
||||
+++ b/blivet/formats/fs.py
|
||||
@@ -27,6 +27,7 @@ import os
|
||||
import tempfile
|
||||
import uuid as uuid_mod
|
||||
import random
|
||||
+import stat
|
||||
|
||||
from parted import fileSystemType, PARTITION_BOOT
|
||||
|
||||
@@ -582,7 +583,7 @@ class FS(DeviceFormat):
|
||||
mountpoint = kwargs.get("mountpoint") or self.mountpoint
|
||||
|
||||
if self._selinux_supported and flags.selinux and "ro" not in self._mount.mount_options(options).split(",") and flags.selinux_reset_fcon:
|
||||
- ret = util.reset_file_context(mountpoint, chroot)
|
||||
+ ret = util.reset_file_context(mountpoint, chroot, stat.S_IFDIR)
|
||||
if not ret:
|
||||
log.warning("Failed to reset SElinux context for newly mounted filesystem root directory to default.")
|
||||
|
||||
diff --git a/blivet/util.py b/blivet/util.py
|
||||
index 48b7818f..f5e0cc1a 100644
|
||||
--- a/blivet/util.py
|
||||
+++ b/blivet/util.py
|
||||
@@ -448,11 +448,11 @@ def get_cow_sysfs_path(dev_path, dev_sysfsPath):
|
||||
##
|
||||
|
||||
|
||||
-def match_path_context(path):
|
||||
+def match_path_context(path, mode=0):
|
||||
""" Return the default SELinux context for the given path. """
|
||||
context = None
|
||||
try:
|
||||
- context = selinux.matchpathcon(os.path.normpath(path), 0)[1]
|
||||
+ context = selinux.matchpathcon(os.path.normpath(path), mode)[1]
|
||||
except OSError as e:
|
||||
log.info("failed to get default SELinux context for %s: %s", path, e)
|
||||
|
||||
@@ -491,7 +491,7 @@ def set_file_context(path, context, root=None):
|
||||
return rc
|
||||
|
||||
|
||||
-def reset_file_context(path, root=None):
|
||||
+def reset_file_context(path, root=None, mode=0):
|
||||
""" Restore the SELinux context of a file to its default value.
|
||||
|
||||
Arguments:
|
||||
@@ -501,12 +501,13 @@ def reset_file_context(path, root=None):
|
||||
Keyword Arguments:
|
||||
|
||||
root an optional chroot string
|
||||
+ mode an optional mode to use
|
||||
|
||||
Return Value:
|
||||
|
||||
If successful, returns the file's new/default context.
|
||||
"""
|
||||
- context = match_path_context(path)
|
||||
+ context = match_path_context(path, mode)
|
||||
if context:
|
||||
if set_file_context(path, context, root=root):
|
||||
return context
|
||||
--
|
||||
2.29.2
|
||||
|
@ -23,7 +23,7 @@ Version: 3.2.2
|
||||
|
||||
#%%global prerelease .b2
|
||||
# prerelease, if defined, should be something like .a1, .b1, .b2.dev1, or .c2
|
||||
Release: 6%{?prerelease}%{?dist}
|
||||
Release: 10%{?prerelease}%{?dist}
|
||||
Epoch: 1
|
||||
License: LGPLv2+
|
||||
Group: System Environment/Libraries
|
||||
@ -42,6 +42,15 @@ Patch7: 0008-set-allowed-disk-labels-for-s390x-as-standard-ones-plus-dasd.patch
|
||||
Patch8: 0009-Do-not-use-BlockDev-utils_have_kernel_module-to-check-for-modules.patch
|
||||
Patch9: 0010-Fix-name-resolution-for-MD-devices-and-partitions-on.patch
|
||||
Patch10: 0011-Fix-ignoring-disk-devices-with-parents-or-children.patch
|
||||
Patch11: 0012-xfs-grow-support.patch
|
||||
Patch12: 0013-Do-not-limit-swap-to-128-GiB.patch
|
||||
Patch13: 0014-Use-UnusableConfigurationError-for-patially-hidden-multipath-devices.patch
|
||||
Patch14: 0015-Fix-possible-UnicodeDecodeError-when-reading-model-f.patch
|
||||
Patch15: 0016-Basic-LVM-VDO-support.patch
|
||||
Patch16: 0017-Let-parted-fix-fixable-issues-with-partition-table.patch
|
||||
Patch17: 0018-Fix-possible-UnicodeDecodeError-when-reading-sysfs-a.patch
|
||||
Patch18: 0019-LVM-VDO-support.patch
|
||||
Patch19: 0020-apply-directory-s-SELinux-context-to-freshly-created.patch
|
||||
|
||||
# Versions of required components (done so we make sure the buildrequires
|
||||
# match the requires versions of things).
|
||||
@ -203,6 +212,32 @@ configuration.
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Mar 08 2021 Vojtech Trefny <vtrefny@redhat.com> - 3.2.2-10
|
||||
- apply directory's SELinux context to freshly created mount points
|
||||
Resolves: rhbz#1934076
|
||||
|
||||
* Tue Feb 9 2021 Vojtech Trefny <vtrefny@redhat.com> - 3.2.2-9
|
||||
- LVM VDO support
|
||||
Resolves: rhbz#1509337
|
||||
|
||||
* Mon Jan 11 2021 Vojtech Trefny <vtrefny@redhat.com> - 3.2.2-8
|
||||
- Let parted fix fixable issues with partition table
|
||||
Resolves: rhbz#1846869
|
||||
- Fix possible UnicodeDecodeError when reading sysfs attributes
|
||||
Resolves: rhbz#1849326
|
||||
|
||||
* Wed Nov 18 2020 Vojtech Trefny <vtrefny@redhat.com> - 3.2.2-7
|
||||
- Add support for XFS format grow
|
||||
Resolves: rhbz#1862349
|
||||
- Do not limit swap to 128 GiB
|
||||
Resolves: rhbz#1656485
|
||||
- Use UnusableConfigurationError for partially hidden multipath devices
|
||||
Resolves: rhbz#1877052
|
||||
- Fix possible UnicodeDecodeError when reading model from sysfs
|
||||
Resolves: rhbz#1849326
|
||||
- Add basic support for LVM VDO devices
|
||||
Resolves: rhbz#1828745
|
||||
|
||||
* Thu Aug 20 2020 Vojtech Trefny <vtrefny@redhat.com> - 3.2.2-6
|
||||
- Fix name resolution for MD devices and partitions on them
|
||||
Resolves: rhbz#1862904
|
||||
|
Loading…
Reference in New Issue
Block a user