[master 13/13] Add test for LUKS format resize
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
---
tests/formats_test/luks_test.py | 47 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 tests/formats_test/luks_test.py
diff --git a/tests/formats_test/luks_test.py b/tests/formats_test/luks_test.py
new file mode 100644
index 0000000..ab13334
--- /dev/null
+++ b/tests/formats_test/luks_test.py
@@ -0,0 +1,47 @@
+from blivet.formats.luks import LUKS
+
+from blivet.size import Size
+
+from tests import loopbackedtestcase
+
+
+class LUKSTestCase(loopbackedtestcase.LoopBackedTestCase):
+
+ def __init__(self, methodName='run_test'):
+ super().__init__(methodName=methodName, device_spec=[Size("100 MiB")])
+ self.fmt = LUKS(passphrase="password")
+
+ def test_size(self):
+ self.fmt.device = self.loop_devices[0]
+
+ # create and open the luks format
+ self.fmt.create()
+ self.fmt.setup()
+
+ # without update_size_info size should be 0
+ self.assertEqual(self.fmt.current_size, Size(0))
+
+ # get current size
+ self.fmt.update_size_info()
+ self.assertGreater(self.fmt.current_size, Size(0))
+
+ def test_resize(self):
+ self.fmt.device = self.loop_devices[0]
+
+ # create and open the luks format
+ self.fmt.create()
+ self.fmt.setup()
+
+ # get current size to make format resizable
+ self.assertFalse(self.fmt.resizable)
+ self.fmt.update_size_info()
+ self.assertTrue(self.fmt.resizable)
+
+ # resize the format
+ new_size = Size("50 MiB")
+ self.fmt.target_size = new_size
+ self.fmt.do_resize()
+
+ # get current size
+ self.fmt.update_size_info()
+ self.assertEqual(self.fmt.current_size, new_size)
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/436fe931d787a55138f18efcf471...
8 years, 4 months
[master 12/13] Add a task for finding the size of a LUKS device
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
---
blivet/tasks/lukstasks.py | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/blivet/tasks/lukstasks.py b/blivet/tasks/lukstasks.py
index 0fa59d7..f3556cb 100644
--- a/blivet/tasks/lukstasks.py
+++ b/blivet/tasks/lukstasks.py
@@ -28,13 +28,43 @@
from ..devicelibs import crypto
from ..errors import LUKSError
-from ..size import Size
from . import availability
from . import task
from . import dfresize
+class LUKSSize(task.BasicApplication):
+ """ Obtain information about the size of a LUKS format. """
+
+ ext = availability.BLOCKDEV_CRYPTO_PLUGIN
+
+ description = "size of a luks device"
+
+ def __init__(self, a_luks):
+ """ Initializer.
+
+ :param :class:`~.formats.luks.LUKS` a_luks: a LUKS format object
+ """
+ self.luks = a_luks
+
+ def do_task(self):
+ """ Returns the size of the luks format.
+
+ :returns: the size of the luks format
+ :rtype: :class:`~.size.Size`
+ :raises :class:`~.errors.LUKSError`: if size cannot be obtained
+ """
+
+ try:
+ dm_dev = blockdev.dm.node_from_name(self.luks.map_name)
+ blocks = int(util.get_sysfs_attr("/sys/block/%s" % dm_dev, "size") or "0")
+ except blockdev.CryptoError as e:
+ raise LUKSError(e)
+
+ return blocks * crypto.SECTOR_SIZE
+
+
class LUKSResize(task.BasicApplication, dfresize.DFResizeTask):
""" Handle resize of LUKS device. """
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/fc6fd9f8ae61b20a8f69bd8d0165...
8 years, 4 months
[master 11/13] Use DeviceFormatError and FormatResizeError in
DeviceFormat
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
Intead of raising "filesystem" exceptions (FSError and FSResizeError).
---
blivet/errors.py | 7 +++++++
blivet/formats/__init__.py | 18 ++++++++++--------
blivet/osinstall.py | 4 ++--
3 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/blivet/errors.py b/blivet/errors.py
index c446b28..809638b 100644
--- a/blivet/errors.py
+++ b/blivet/errors.py
@@ -86,6 +86,13 @@ class FormatTeardownError(DeviceFormatError):
pass
+class FormatResizeError(DeviceFormatError):
+
+ def __init__(self, message, details):
+ DeviceFormatError.__init__(self, message)
+ self.details = details
+
+
class DMRaidMemberError(DeviceFormatError):
pass
diff --git a/blivet/formats/__init__.py b/blivet/formats/__init__.py
index 1c26ed4..08aad82 100644
--- a/blivet/formats/__init__.py
+++ b/blivet/formats/__init__.py
@@ -40,7 +40,7 @@
from ..threads import SynchronizedMeta
from ..flags import flags
-from ..errors import FSError, FSResizeError #FIXME
+from ..errors import FSError, FSResizeError, LUKSError, FormatResizeError
from ..tasks import fsinfo
from ..tasks import fsresize
@@ -419,10 +419,10 @@ def _set_target_size(self, newsize):
raise ValueError("new size must be of type Size")
if not self.exists:
- raise FSError("filesystem has not been created")
+ raise DeviceFormatError("format has not been created")
if not self.resizable:
- raise FSError("filesystem is not resizable")
+ raise DeviceFormatError("format is not resizable")
if newsize < self.min_size:
raise ValueError("requested size %s must be at least minimum size %s" % (newsize, self.min_size))
@@ -463,13 +463,13 @@ def update_size_info(self):
def do_resize(self):
""" Resize this filesystem based on this instance's target_size attr.
- :raises: FSResizeError, FSError
+ :raises: FSResizeError, FormatResizeError
"""
if not self.exists:
- raise FSResizeError("filesystem does not exist", self.device)
+ raise FormatResizeError("format does not exist", self.device)
if not self.resizable:
- raise FSResizeError("filesystem not resizable", self.device)
+ raise FormatResizeError("format not resizable", self.device)
if self.target_size == self.current_size:
return
@@ -479,7 +479,7 @@ def do_resize(self):
# tmpfs mounts don't need an existing device node
if not self.device == "tmpfs" and not os.path.exists(self.device):
- raise FSResizeError("device does not exist", self.device)
+ raise FormatResizeError("device does not exist", self.device)
# The first minimum size can be incorrect if the fs was not
# properly unmounted. After do_check the minimum size will be correct
@@ -489,7 +489,7 @@ def do_resize(self):
# Check again if resizable is True, as update_size_info() can change that
if not self.resizable:
- raise FSResizeError("filesystem not resizable", self.device)
+ raise FormatResizeError("format not resizable", self.device)
if self.target_size < self.min_size:
self.target_size = self.min_size
@@ -530,6 +530,8 @@ def do_resize(self):
self._resize.do_task()
except FSError as e:
raise FSResizeError(e, self.device)
+ except LUKSError as e:
+ raise FormatResizeError(e, self.device)
self._post_resize()
diff --git a/blivet/osinstall.py b/blivet/osinstall.py
index 86f6ba9..ec6dd21 100644
--- a/blivet/osinstall.py
+++ b/blivet/osinstall.py
@@ -36,7 +36,7 @@
from .storage_log import log_exception_info
from .devices import FileDevice, NFSDevice, NoDevice, OpticalDevice, NetworkStorageDevice, DirectoryDevice
-from .errors import FSTabTypeMismatchError, UnrecognizedFSTabEntryError, StorageError, FSResizeError, UnknownSourceDeviceError
+from .errors import FSTabTypeMismatchError, UnrecognizedFSTabEntryError, StorageError, FSResizeError, FormatResizeError, UnknownSourceDeviceError
from .formats import get_device_format_class
from .formats import get_format
from .flags import flags
@@ -1112,7 +1112,7 @@ def turn_on_filesystems(storage, mount_only=False, callbacks=None):
try:
storage.do_it(callbacks)
- except FSResizeError as e:
+ except (FSResizeError, FormatResizeError) as e:
if error_handler.cb(e) == ERROR_RAISE:
raise
except Exception as e:
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/1d000b0c04d488205e3224e72af9...
8 years, 4 months
[master 10/13] Add LUKS resize support to resize_device method
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
---
blivet/blivet.py | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/blivet/blivet.py b/blivet/blivet.py
index 19ff1b3..06d8e13 100644
--- a/blivet/blivet.py
+++ b/blivet/blivet.py
@@ -38,6 +38,7 @@
from .deviceaction import ActionDestroyFormat, ActionResizeDevice, ActionResizeFormat
from .devicelibs.edd import get_edd_dict
from .devicelibs.btrfs import MAIN_VOLUME_ID
+from .devicelibs.crypto import LUKS_METADATA_SIZE
from .errors import StorageError
from .size import Size
from .devicetree import DeviceTree
@@ -1138,22 +1139,33 @@ def resize_device(self, device, new_size):
if device.protected:
raise ValueError("cannot modify protected device")
- classes = []
+ actions = []
+
if device.resizable:
- classes.append(ActionResizeDevice)
+ actions.append(ActionResizeDevice(device, new_size))
+
+ if device.format.type == "luks" and device.children:
+ luks_dev = device.children[0]
+
+ if luks_dev.resizable:
+ actions.append(ActionResizeDevice(luks_dev, new_size - LUKS_METADATA_SIZE))
- if device.format.resizable:
- classes.append(ActionResizeFormat)
+ if luks_dev.format.resizable:
+ actions.append(ActionResizeFormat(luks_dev, new_size - LUKS_METADATA_SIZE))
+
+ else:
+ if device.format.resizable:
+ actions.append(ActionResizeFormat(device, new_size))
- if not classes:
+ if not actions:
raise ValueError("device cannot be resized")
# if this is a shrink, schedule the format resize first
if new_size < device.size:
- classes.reverse()
+ actions.reverse()
- for action_class in classes:
- self.devicetree.actions.add(action_class(device, new_size))
+ for action in actions:
+ self.devicetree.actions.add(action)
def format_by_default(self, device):
"""Return whether the device should be reformatted by default."""
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/3f7c5ac44dca235e900afc3c0148...
8 years, 4 months
[master 9/13] Define min_size for encrypted partitions
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
For encrypted partitions, min_size depends on the LUKS device
format min_size.
---
blivet/devices/partition.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py
index 6487625..a5a9c1c 100644
--- a/blivet/devices/partition.py
+++ b/blivet/devices/partition.py
@@ -36,6 +36,7 @@
from .. import udev
from ..formats import DeviceFormat, get_format
from ..size import Size, MiB
+from ..devicelibs.crypto import LUKS_METADATA_SIZE
import logging
log = logging.getLogger("blivet")
@@ -826,7 +827,14 @@ def min_size(self):
min_size = self.align_target_size(max(Size("1 KiB"), self.disk.format.alignment.grainSize))
else:
- min_size = super(PartitionDevice, self).min_size
+ if self.format.type == "luks" and self.children:
+ if self.resizable:
+ min_size = self.children[0].min_size + LUKS_METADATA_SIZE
+ else:
+ min_size = self.current_size
+
+ else:
+ min_size = self.format.min_size if self.resizable else self.current_size
if self.resizable and min_size:
# Adjust the min size as needed so that aligning the end sector
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/e60e7a66b5082119799a381e5a25...
8 years, 4 months
[master 8/13] Do not teardown partition when resizing encrypted
partition
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
Running teardown on luks encrypted partition would close the LUKS
device on it. Making it impossible to resize. Teardown only the
filesystem on the LUKS device instead.
---
blivet/devices/partition.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py
index 5033c45..6487625 100644
--- a/blivet/devices/partition.py
+++ b/blivet/devices/partition.py
@@ -663,7 +663,11 @@ def _pre_resize(self):
if not self.exists:
raise errors.DeviceError("device has not been created", self.name)
- self.teardown()
+ # don't teardown when resizing luks
+ if self.format.type == "luks" and self.children:
+ self.children[0].format.teardown()
+ else:
+ self.teardown()
if not self.sysfs_path:
return
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/0b5c66954ca5eda2f557517541f1...
8 years, 4 months
[master 7/13] Make partitions with children resizable
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
---
blivet/devices/partition.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py
index ce358e3..5033c45 100644
--- a/blivet/devices/partition.py
+++ b/blivet/devices/partition.py
@@ -663,9 +663,6 @@ def _pre_resize(self):
if not self.exists:
raise errors.DeviceError("device has not been created", self.name)
- if not self.isleaf and not self.is_extended:
- raise errors.DeviceError("Cannot destroy non-leaf device", self.name)
-
self.teardown()
if not self.sysfs_path:
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/c735f7f057e63698e24e7f3da529...
8 years, 4 months
[master 6/13] Make LUKS format resizable
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
---
blivet/formats/luks.py | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/blivet/formats/luks.py b/blivet/formats/luks.py
index 4d9347d..d71b7d5 100644
--- a/blivet/formats/luks.py
+++ b/blivet/formats/luks.py
@@ -33,7 +33,8 @@
from . import DeviceFormat, register_device_format
from ..flags import flags
from ..i18n import _, N_
-from ..tasks import availability
+from ..tasks import availability, lukstasks
+from ..size import Size
import logging
log = logging.getLogger("blivet")
@@ -50,8 +51,13 @@ class LUKS(DeviceFormat):
_linux_native = True # for clearpart
_packages = ["cryptsetup"] # required packages
_min_size = crypto.LUKS_METADATA_SIZE
+ _max_size = Size("16 EiB")
_plugin = availability.BLOCKDEV_CRYPTO_PLUGIN
+ _size_info_class = lukstasks.LUKSSize
+ _resize_class = lukstasks.LUKSResize
+ _resizable = True
+
def __init__(self, **kwargs):
"""
:keyword device: the path to the underlying device
@@ -85,6 +91,10 @@ def __init__(self, **kwargs):
"""
log_method_call(self, **kwargs)
DeviceFormat.__init__(self, **kwargs)
+
+ self._size_info = self._size_info_class(self)
+ self._resize = self._resize_class(self)
+
self.cipher = kwargs.get("cipher")
self.key_size = kwargs.get("key_size")
self.map_name = kwargs.get("name")
@@ -111,6 +121,10 @@ def __init__(self, **kwargs):
elif not self.map_name and self.device:
self.map_name = "luks-%s" % os.path.basename(self.device)
+ if flags.installer_mode and self._resize.available:
+ # if you want current/min size you have to call update_size_info
+ self.update_size_info()
+
def __repr__(self):
s = DeviceFormat.__repr__(self)
if self.__passphrase:
@@ -179,6 +193,21 @@ def status(self):
return False
return os.path.exists("/dev/mapper/%s" % self.map_name)
+ def update_size_info(self):
+ """ Update this format's current size. """
+
+ self._resizable = False
+
+ if not self.status:
+ return
+
+ try:
+ self._size = self._size_info.do_task()
+ except LUKSError as e:
+ log.warning("Failed to obtain current size for device %s: %s", self.device, e)
+ else:
+ self._resizable = True
+
def _pre_setup(self, **kwargs):
if not self.configured:
raise LUKSError("luks device not configured")
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/f5348176b3b30ee1ce92a146fad1...
8 years, 4 months
[master 5/13] Make LUKSDevice resizable
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
---
blivet/devices/luks.py | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/blivet/devices/luks.py b/blivet/devices/luks.py
index 1fee1b8..48a5ecd 100644
--- a/blivet/devices/luks.py
+++ b/blivet/devices/luks.py
@@ -22,6 +22,9 @@
# device backend modules
from ..devicelibs import crypto
+from ..storage_log import log_method_call
+from ..size import Size
+
import logging
log = logging.getLogger("blivet")
@@ -33,6 +36,7 @@ class LUKSDevice(DMCryptDevice):
""" A mapped LUKS device. """
_type = "luks/dm-crypt"
+ _resizable = True
_packages = ["cryptsetup"]
def __init__(self, name, fmt=None, size=None, uuid=None,
@@ -65,10 +69,37 @@ def raw_device(self):
def size(self):
if not self.exists:
size = self.slave.size - crypto.LUKS_METADATA_SIZE
+ elif self.resizable and self.target_size != Size(0):
+ size = self.target_size
else:
size = self.current_size
return size
+ @property
+ def min_size(self):
+ """ The minimum size this device can be. """
+ return self.align_target_size(self.format.min_size) if self.resizable else self.current_size
+
+ def _set_target_size(self, newsize):
+ super()._set_target_size(newsize)
+
+ self.slave.format.target_size = newsize
+
+ @property
+ def resizable(self):
+ """ Can this device be resized? """
+ return (self._resizable and self.exists and self.format.resizable and
+ self.slave.resizable)
+
+ def _pre_resize(self):
+ self.format.teardown()
+
+ def resize(self):
+ log_method_call(self, self.name, status=self.status)
+ self._pre_resize()
+
+ self.slave.format.do_resize()
+
def _post_create(self):
self.name = self.slave.format.map_name
StorageDevice._post_create(self)
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/ff617e752871689848f56258c318...
8 years, 4 months
[master 4/13] Make lukstasks and dfresize task pep8 compliant
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
---
blivet/tasks/dfresize.py | 2 ++
blivet/tasks/fsresize.py | 3 ++-
blivet/tasks/lukstasks.py | 8 ++++++--
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/blivet/tasks/dfresize.py b/blivet/tasks/dfresize.py
index 856707b..2390a8d 100644
--- a/blivet/tasks/dfresize.py
+++ b/blivet/tasks/dfresize.py
@@ -25,12 +25,14 @@
from . import task
+
@add_metaclass(abc.ABCMeta)
class DFResizeTask(task.Task):
""" The abstract properties that any resize task must have. """
unit = abc.abstractproperty(doc="Resize unit.")
+
class UnimplementedDFResize(task.UnimplementedTask, DFResizeTask):
def __init__(self, a_df):
diff --git a/blivet/tasks/fsresize.py b/blivet/tasks/fsresize.py
index 417cafc..e7e2698 100644
--- a/blivet/tasks/fsresize.py
+++ b/blivet/tasks/fsresize.py
@@ -29,11 +29,12 @@
from . import availability
from . import task
+from . import fstask
from . import dfresize
@add_metaclass(abc.ABCMeta)
-class FSResizeTask(dfresize.DFResizeTask):
+class FSResizeTask(fstask.FSTask):
""" The abstract properties that any resize task must have. """
size_fmt = abc.abstractproperty(doc="Size format string.")
diff --git a/blivet/tasks/lukstasks.py b/blivet/tasks/lukstasks.py
index 27920c1..0fa59d7 100644
--- a/blivet/tasks/lukstasks.py
+++ b/blivet/tasks/lukstasks.py
@@ -19,6 +19,9 @@
#
# Red Hat Author(s): Anne Mulhern <amulhern(a)redhat.com>
+import gi
+gi.require_version("BlockDev", "1.0")
+
from gi.repository import BlockDev as blockdev
from .. import util
@@ -31,6 +34,7 @@
from . import task
from . import dfresize
+
class LUKSResize(task.BasicApplication, dfresize.DFResizeTask):
""" Handle resize of LUKS device. """
@@ -48,9 +52,9 @@ def __init__(self, a_luks):
"""
self.luks = a_luks
- def doTask(self):
+ def do_task(self):
""" Resizes the LUKS format. """
try:
- blockdev.crypto.luks_resize(self.luks.mapName, self.luks.targetSize.convertTo(self.unit))
+ blockdev.crypto.luks_resize(self.luks.map_name, self.luks.target_size.convert_to(self.unit))
except blockdev.CryptoError as e:
raise LUKSError(e)
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/a207baa57f802f84a2896f99e198...
8 years, 4 months