[master 3/13] Make a top level device format resizing task class.
by dashea
From: mulhern <amulhern(a)redhat.com>
Adjust the task class heirarchy accordingly.
Signed-off-by: mulhern <amulhern(a)redhat.com>
---
blivet/tasks/dfresize.py | 45 +++++++++++++++++++++++++++++++++++++++++++++
blivet/tasks/fsresize.py | 12 +++---------
2 files changed, 48 insertions(+), 9 deletions(-)
create mode 100644 blivet/tasks/dfresize.py
diff --git a/blivet/tasks/dfresize.py b/blivet/tasks/dfresize.py
new file mode 100644
index 0000000..856707b
--- /dev/null
+++ b/blivet/tasks/dfresize.py
@@ -0,0 +1,45 @@
+# dfresize.py
+# DeviceFormat resizing classes.
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Anne Mulhern <amulhern(a)redhat.com>
+
+import abc
+
+from six import add_metaclass
+
+from . import task
+
+(a)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):
+ """ Initializer.
+
+ :param DeviceFormat a_df: a device format object
+ """
+ self.df = a_df
+
+ @property
+ def unit(self):
+ raise NotImplementedError()
diff --git a/blivet/tasks/fsresize.py b/blivet/tasks/fsresize.py
index 343acaf..417cafc 100644
--- a/blivet/tasks/fsresize.py
+++ b/blivet/tasks/fsresize.py
@@ -28,16 +28,14 @@
from ..import util
from . import availability
-from . import fstask
from . import task
+from . import dfresize
@add_metaclass(abc.ABCMeta)
-class FSResizeTask(fstask.FSTask):
-
+class FSResizeTask(dfresize.DFResizeTask):
""" The abstract properties that any resize task must have. """
- unit = abc.abstractproperty(doc="Resize unit.")
size_fmt = abc.abstractproperty(doc="Size format string.")
@@ -135,11 +133,7 @@ def args(self):
return ['-o', ",".join(options), self.fs._type, self.fs.system_mountpoint]
-class UnimplementedFSResize(task.UnimplementedTask, FSResizeTask):
-
- @property
- def unit(self):
- raise NotImplementedError()
+class UnimplementedFSResize(dfresize.UnimplementedDFResize, FSResizeTask):
@property
def size_fmt(self):
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/57e239da203fb6dcb69a97ed2c5b...
8 years, 3 months
[master 2/13] Add a LUKS resize task.
by dashea
From: mulhern <amulhern(a)redhat.com>
Signed-off-by: mulhern <amulhern(a)redhat.com>
---
blivet/devicelibs/crypto.py | 1 +
blivet/tasks/lukstasks.py | 56 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
create mode 100644 blivet/tasks/lukstasks.py
diff --git a/blivet/devicelibs/crypto.py b/blivet/devicelibs/crypto.py
index 7d3bc15..fbef943 100644
--- a/blivet/devicelibs/crypto.py
+++ b/blivet/devicelibs/crypto.py
@@ -25,5 +25,6 @@
LUKS_METADATA_SIZE = Size("2 MiB")
MIN_CREATE_ENTROPY = 256 # bits
+SECTOR_SIZE = Size("512 B")
EXTERNAL_DEPENDENCIES = [availability.BLOCKDEV_CRYPTO_PLUGIN]
diff --git a/blivet/tasks/lukstasks.py b/blivet/tasks/lukstasks.py
new file mode 100644
index 0000000..27920c1
--- /dev/null
+++ b/blivet/tasks/lukstasks.py
@@ -0,0 +1,56 @@
+# lukstasks.py
+# Tasks for a LUKS format.
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Anne Mulhern <amulhern(a)redhat.com>
+
+from gi.repository import BlockDev as blockdev
+
+from .. import util
+
+from ..devicelibs import crypto
+from ..errors import LUKSError
+from ..size import Size
+
+from . import availability
+from . import task
+from . import dfresize
+
+class LUKSResize(task.BasicApplication, dfresize.DFResizeTask):
+ """ Handle resize of LUKS device. """
+
+ description = "resize luks device"
+
+ ext = availability.BLOCKDEV_CRYPTO_PLUGIN
+
+ # units for specifying new size
+ unit = crypto.SECTOR_SIZE
+
+ def __init__(self, a_luks):
+ """ Initializer.
+
+ :param :class:`~.formats.luks.LUKS` a_luks: a LUKS format object
+ """
+ self.luks = a_luks
+
+ def doTask(self):
+ """ Resizes the LUKS format. """
+ try:
+ blockdev.crypto.luks_resize(self.luks.mapName, self.luks.targetSize.convertTo(self.unit))
+ except blockdev.CryptoError as e:
+ raise LUKSError(e)
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/149a9dcb1416d91e68e9a9f76aae...
8 years, 3 months
Updated: [rhinstaller/blivet/pulls/308 master] LUKS resize
by dashea
LUKS encrypted partitions resize support.
Known issues:
- `LUKSFormat` has "wrong" `min_size` -- because minimal size depends on minimal size of LUKS device's format, it's not possible to set it for LUKS format. Slave device, LUKS device and filesystem have correct min_size.
- Both `LUKSFormat` and `LUKSDevice` don't have `max_size` -- it depends on the slave device. We don't set max_size for formats (just limits), so it probably makes sense to set the max size correctly just for the slave device. But it would be easy to set the max_size correctly for the LUKS device.
- Tasks -- I just took code from mulhern's original pull request and made changes to make pep8 and pylint happy. It works, but I don't have idea how :)
- `FSError` and `FSResizeError` -- original `do_resize` and `_set_target_size` raised only these exceptions but it doesn't make sense for "non-filesystems". I've tried to change it to raise `DeviceFormatError` and `FormatResizeError` where it makes sense. Not sure if this is the best way.
- There are no tests. I will add some next week.
--
To view this pull request on github, visit https://github.com/rhinstaller/blivet/pull/308
8 years, 3 months
[master 1/13] Move resize related methods from FS to DeviceFormat
by dashea
From: Vojtech Trefny <vtrefny(a)redhat.com>
This includes update_min_size, do_resize, current_size,
target_size, _get_target_size, _set_target_size, _get_size methods
and properties.
---
blivet/formats/__init__.py | 176 +++++++++++++++++++++++++++++++++++++++++----
blivet/formats/fs.py | 149 ++------------------------------------
2 files changed, 168 insertions(+), 157 deletions(-)
diff --git a/blivet/formats/__init__.py b/blivet/formats/__init__.py
index d67d6f4..1c26ed4 100644
--- a/blivet/formats/__init__.py
+++ b/blivet/formats/__init__.py
@@ -36,8 +36,17 @@
from ..storage_log import log_method_call
from ..errors import DeviceFormatError, FormatCreateError, FormatDestroyError, FormatSetupError
from ..i18n import N_
-from ..size import Size
+from ..size import Size, ROUND_DOWN, unit_str
from ..threads import SynchronizedMeta
+from ..flags import flags
+
+from ..errors import FSError, FSResizeError #FIXME
+
+from ..tasks import fsinfo
+from ..tasks import fsresize
+from ..tasks import fssize
+from ..tasks import fsck
+from ..tasks import fsminsize
import logging
log = logging.getLogger("blivet")
@@ -175,6 +184,11 @@ class DeviceFormat(ObjectID, metaclass=SynchronizedMeta):
_hidden = False # hide devices with this formatting?
_ks_mountpoint = None
+ _resize_class = fsresize.UnimplementedFSResize
+ _size_info_class = fssize.UnimplementedFSSize
+ _info_class = fsinfo.UnimplementedFSInfo
+ _minsize_class = fsminsize.UnimplementedFSMinSize
+
def __init__(self, **kwargs):
"""
:keyword device: The path to the device node.
@@ -203,6 +217,22 @@ def __init__(self, **kwargs):
self.options = kwargs.get("options")
self._create_options = kwargs.get("create_options")
+ # Create task objects
+ self._info = self._info_class(self)
+ self._resize = self._resize_class(self)
+ # These two may depend on info class, so create them after
+ self._minsize = self._minsize_class(self)
+ self._size_info = self._size_info_class(self)
+
+ # format size does not necessarily equal device size
+ self._size = kwargs.get("size", Size(0))
+ self._target_size = self._size
+ self._min_instance_size = Size(0) # min size of this DeviceFormat instance
+
+ # Resize operations are limited to error-free formats whose current
+ # size is known.
+ self._resizable = False
+
def __repr__(self):
s = ("%(classname)s instance (%(id)s) object id %(object_id)d--\n"
" type = %(type)s name = %(name)s status = %(status)s\n"
@@ -380,6 +410,139 @@ def notify_kernel(self):
except (ValueError, IOError) as e:
log.warning("failed to notify kernel of change: %s", e)
+ def _set_target_size(self, newsize):
+ """ Set the target size for this filesystem.
+
+ :param :class:`~.size.Size` newsize: the newsize
+ """
+ if not isinstance(newsize, Size):
+ raise ValueError("new size must be of type Size")
+
+ if not self.exists:
+ raise FSError("filesystem has not been created")
+
+ if not self.resizable:
+ raise FSError("filesystem is not resizable")
+
+ if newsize < self.min_size:
+ raise ValueError("requested size %s must be at least minimum size %s" % (newsize, self.min_size))
+
+ if self.max_size and newsize >= self.max_size:
+ raise ValueError("requested size %s must be less than maximum size %s" % (newsize, self.max_size))
+
+ self._target_size = newsize
+
+ def _get_target_size(self):
+ """ Get this filesystem's target size. """
+ return self._target_size
+
+ target_size = property(_get_target_size, _set_target_size,
+ doc="Target size for this filesystem")
+
+ def _get_size(self):
+ """ Get this filesystem's size. """
+ return self.target_size if self.resizable else self._size
+
+ size = property(_get_size, doc="This filesystem's size, accounting "
+ "for pending changes")
+
+ @property
+ def min_size(self):
+ # If self._min_instance_size is not 0, then it should be no less than
+ # self._min_size, by definition, and since a non-zero value indicates
+ # that it was obtained, it is the preferred value.
+ # If self._min_instance_size is less than self._min_size,
+ # but not 0, then there must be some mistake, so better to use
+ # self._min_size.
+ return max(self._min_instance_size, self._min_size)
+
+ def update_size_info(self):
+ """ Update this format's current and minimum size (for resize). """
+ pass
+
+ def do_resize(self):
+ """ Resize this filesystem based on this instance's target_size attr.
+
+ :raises: FSResizeError, FSError
+ """
+ if not self.exists:
+ raise FSResizeError("filesystem does not exist", self.device)
+
+ if not self.resizable:
+ raise FSResizeError("filesystem not resizable", self.device)
+
+ if self.target_size == self.current_size:
+ return
+
+ if not self._resize.available:
+ return
+
+ # 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)
+
+ # The first minimum size can be incorrect if the fs was not
+ # properly unmounted. After do_check the minimum size will be correct
+ # so run the check one last time and bump up the size if it was too
+ # small.
+ self.update_size_info()
+
+ # Check again if resizable is True, as update_size_info() can change that
+ if not self.resizable:
+ raise FSResizeError("filesystem not resizable", self.device)
+
+ if self.target_size < self.min_size:
+ self.target_size = self.min_size
+ log.info("Minimum size changed, setting target_size on %s to %s",
+ self.device, self.target_size)
+
+ # Bump target size to nearest whole number of the resize tool's units.
+ # We always round down because the fs has to fit on whatever device
+ # contains it. To round up would risk quietly setting a target size too
+ # large for the device to hold.
+ rounded = self.target_size.round_to_nearest(self._resize.unit,
+ rounding=ROUND_DOWN)
+
+ # 1. target size was between the min size and max size values prior to
+ # rounding (see _set_target_size)
+ # 2. we've just rounded the target size down (or not at all)
+ # 3. the minimum size is already either rounded (see _get_min_size) or is
+ # equal to the current size (see update_size_info)
+ # 5. the minimum size is less than or equal to the current size (see
+ # _get_min_size)
+ #
+ # This, I think, is sufficient to guarantee that the rounded target size
+ # is greater than or equal to the minimum size.
+
+ # It is possible that rounding down a target size greater than the
+ # current size would move it below the current size, thus changing the
+ # direction of the resize. That means the target size was less than one
+ # unit larger than the current size, and we should do nothing and return
+ # early.
+ if self.target_size > self.current_size and rounded < self.current_size:
+ log.info("rounding target size down to next %s obviated resize of "
+ "filesystem on %s", unit_str(self._resize.unit), self.device)
+ return
+ else:
+ self.target_size = rounded
+
+ try:
+ self._resize.do_task()
+ except FSError as e:
+ raise FSResizeError(e, self.device)
+
+ self._post_resize()
+
+ def _post_resize(self):
+ # XXX must be a smarter way to do this
+ self._size = self.target_size
+ self.notify_kernel()
+
+ @property
+ def current_size(self):
+ """ The filesystem's current actual size. """
+ return self._size if self.exists else Size(0)
+
def create(self, **kwargs):
""" Write the formatting to the specified block device.
@@ -609,17 +772,6 @@ def max_size(self):
return self._max_size
@property
- def min_size(self):
- """ Minimum size for this format instance.
-
- :returns: the minimum size for this format instance
- :rtype: :class:`~.size.Size`
-
- A value of 0 indicates an unknown size.
- """
- return self._min_size
-
- @property
def hidden(self):
""" Whether devices with this formatting should be hidden in UIs. """
return self._hidden
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
index f69ac90..ba2a1f1 100644
--- a/blivet/formats/fs.py
+++ b/blivet/formats/fs.py
@@ -40,14 +40,14 @@
from ..tasks import fssync
from ..tasks import fswritelabel
from ..errors import FormatCreateError, FSError, FSReadLabelError
-from ..errors import FSWriteLabelError, FSResizeError
+from ..errors import FSWriteLabelError
from . import DeviceFormat, register_device_format
from .. import util
from .. import platform
from ..flags import flags
from ..storage_log import log_exception_info, log_method_call
from .. import arch
-from ..size import Size, ROUND_UP, ROUND_DOWN, unit_str
+from ..size import Size, ROUND_UP
from ..i18n import N_
from .. import udev
from ..mounts import mounts_cache
@@ -66,13 +66,9 @@ class FS(DeviceFormat):
_modules = [] # kernel modules required for support
_labelfs = None # labeling functionality
_fsck_class = fsck.UnimplementedFSCK
- _info_class = fsinfo.UnimplementedFSInfo
- _minsize_class = fsminsize.UnimplementedFSMinSize
_mkfs_class = fsmkfs.UnimplementedFSMkfs
_mount_class = fsmount.FSMount
_readlabel_class = fsreadlabel.UnimplementedFSReadLabel
- _resize_class = fsresize.UnimplementedFSResize
- _size_info_class = fssize.UnimplementedFSSize
_sync_class = fssync.UnimplementedFSSync
_writelabel_class = fswritelabel.UnimplementedFSWriteLabel
# This constant is aquired by testing some filesystems
@@ -109,19 +105,13 @@ def __init__(self, **kwargs):
DeviceFormat.__init__(self, **kwargs)
# Create task objects
- self._info = self._info_class(self)
self._fsck = self._fsck_class(self)
self._mkfs = self._mkfs_class(self)
self._mount = self._mount_class(self)
self._readlabel = self._readlabel_class(self)
- self._resize = self._resize_class(self)
self._sync = self._sync_class(self)
self._writelabel = self._writelabel_class(self)
- # These two may depend on info class, so create them after
- self._minsize = self._minsize_class(self)
- self._size_info = self._size_info_class(self)
-
self._current_info = None # info obtained by _info task
self.mountpoint = kwargs.get("mountpoint")
@@ -129,13 +119,6 @@ def __init__(self, **kwargs):
self.label = kwargs.get("label")
self.fsprofile = kwargs.get("fsprofile")
- # filesystem size does not necessarily equal device size
- self._size = kwargs.get("size", Size(0))
- self._min_instance_size = Size(0) # min size of this FS instance
-
- # Resize operations are limited to error-free filesystems whose current
- # size is known.
- self._resizable = False
if flags.installer_mode and self._resize.available:
# if you want current/min size you have to call update_size_info
try:
@@ -216,42 +199,6 @@ def label_format_ok(self, label):
label = property(lambda s: s._get_label(), lambda s, l: s._set_label(l),
doc="this filesystem's label")
- def _set_target_size(self, newsize):
- """ Set the target size for this filesystem.
-
- :param :class:`~.size.Size` newsize: the newsize
- """
- if not isinstance(newsize, Size):
- raise ValueError("new size must be of type Size")
-
- if not self.exists:
- raise FSError("filesystem has not been created")
-
- if not self.resizable:
- raise FSError("filesystem is not resizable")
-
- if newsize < self.min_size:
- raise ValueError("requested size %s must be at least minimum size %s" % (newsize, self.min_size))
-
- if self.max_size and newsize >= self.max_size:
- raise ValueError("requested size %s must be less than maximum size %s" % (newsize, self.max_size))
-
- self._target_size = newsize
-
- def _get_target_size(self):
- """ Get this filesystem's target size. """
- return self._target_size
-
- target_size = property(_get_target_size, _set_target_size,
- doc="Target size for this filesystem")
-
- def _get_size(self):
- """ Get this filesystem's size. """
- return self.target_size if self.resizable else self._size
-
- size = property(_get_size, doc="This filesystem's size, accounting "
- "for pending changes")
-
def update_size_info(self):
""" Update this filesystem's current and minimum size (for resize). """
@@ -315,16 +262,6 @@ def update_size_info(self):
except (FSError, NotImplementedError) as e:
log.warning("Failed to obtain minimum size for device %s: %s", self.device, e)
- @property
- def min_size(self):
- # If self._min_instance_size is not 0, then it should be no less than
- # self._min_size, by definition, and since a non-zero value indicates
- # that it was obtained, it is the preferred value.
- # If self._min_instance_size is less than self._min_size,
- # but not 0, then there must be some mistake, so better to use
- # self._min_size.
- return max(self._min_instance_size, self._min_size)
-
def _pad_size(self, size):
""" Return a size padded according to some inflating rules.
@@ -346,11 +283,6 @@ def _pad_size(self, size):
return padded
@property
- def current_size(self):
- """ The filesystem's current actual size. """
- return self._size if self.exists else Size(0)
-
- @property
def free(self):
""" The amount of space that can be gained by resizing this
filesystem to its minimum size.
@@ -390,82 +322,9 @@ def _post_create(self, **kwargs):
except FSError as e:
log.warning("Failed to write label (%s) for filesystem %s: %s", self.label, self.type, e)
- def do_resize(self):
- """ Resize this filesystem based on this instance's target_size attr.
-
- :raises: FSResizeError, FSError
- """
- if not self.exists:
- raise FSResizeError("filesystem does not exist", self.device)
-
- if not self.resizable:
- raise FSResizeError("filesystem not resizable", self.device)
-
- if self.target_size == self.current_size:
- return
-
- if not self._resize.available:
- return
-
- # 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)
-
- # The first minimum size can be incorrect if the fs was not
- # properly unmounted. After do_check the minimum size will be correct
- # so run the check one last time and bump up the size if it was too
- # small.
- self.update_size_info()
-
- # Check again if resizable is True, as update_size_info() can change that
- if not self.resizable:
- raise FSResizeError("filesystem not resizable", self.device)
-
- if self.target_size < self.min_size:
- self.target_size = self.min_size
- log.info("Minimum size changed, setting target_size on %s to %s",
- self.device, self.target_size)
-
- # Bump target size to nearest whole number of the resize tool's units.
- # We always round down because the fs has to fit on whatever device
- # contains it. To round up would risk quietly setting a target size too
- # large for the device to hold.
- rounded = self.target_size.round_to_nearest(self._resize.unit,
- rounding=ROUND_DOWN)
-
- # 1. target size was between the min size and max size values prior to
- # rounding (see _set_target_size)
- # 2. we've just rounded the target size down (or not at all)
- # 3. the minimum size is already either rounded (see _get_min_size) or is
- # equal to the current size (see update_size_info)
- # 5. the minimum size is less than or equal to the current size (see
- # _get_min_size)
- #
- # This, I think, is sufficient to guarantee that the rounded target size
- # is greater than or equal to the minimum size.
-
- # It is possible that rounding down a target size greater than the
- # current size would move it below the current size, thus changing the
- # direction of the resize. That means the target size was less than one
- # unit larger than the current size, and we should do nothing and return
- # early.
- if self.target_size > self.current_size and rounded < self.current_size:
- log.info("rounding target size down to next %s obviated resize of "
- "filesystem on %s", unit_str(self._resize.unit), self.device)
- return
- else:
- self.target_size = rounded
-
- try:
- self._resize.do_task()
- except FSError as e:
- raise FSResizeError(e, self.device)
-
+ def _post_resize(self):
self.do_check()
-
- # XXX must be a smarter way to do this
- self._size = self.target_size
- self.notify_kernel()
+ super(FS, self)._post_resize()
def do_check(self):
""" Run a filesystem check.
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/d664e9f9711229b1c6031af9db3b...
8 years, 3 months
[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/61010101a8c9c53820f1d77f8857...
8 years, 3 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/409e38c00fb8e71b39ccbd2271c8...
8 years, 3 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/98758de053c55328e49ab3b0f7af...
8 years, 3 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/dd80cd570ac4d6dcd9c54e8f5bc7...
8 years, 3 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/bd3d47eaafe6f10a7720869405b8...
8 years, 3 months