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...