[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [PATCH 03/13] Add method to get size of existing filesystems.



On Fri, 2009-03-13 at 18:09 -1000, David Cantrell wrote:
> The _getExistingSize() method in class FS will using the filesystem
> info/dump utility to figure out the size of the filesystem.  Each
> filesystem must define _infofs, _defaultInfoOptions, and
> _existingSizeFields.

Looks okay to me. This is kind of scary stuff, but I think that's just
how it is when you have to parse output like this.

Dave


> ---
>  storage/formats/fs.py |   93 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 92 insertions(+), 1 deletions(-)
> 
> diff --git a/storage/formats/fs.py b/storage/formats/fs.py
> index f467852..5fbe62d 100644
> --- a/storage/formats/fs.py
> +++ b/storage/formats/fs.py
> @@ -18,6 +18,7 @@
>  # Red Hat, Inc.
>  #
>  # Red Hat Author(s): Dave Lehman <dlehman redhat com>
> +#                    David Cantrell <dcantrell redhat com>
>  #
>  
>  """ Filesystem classes for use by anaconda.
> @@ -120,12 +121,15 @@ class FS(DeviceFormat):
>      _labelfs = ""                        # labeling utility
>      _fsck = ""                           # fs check utility
>      _migratefs = ""                      # fs migration utility
> +    _infofs = ""                         # fs info utility
>      _defaultFormatOptions = []           # default options passed to mkfs
>      _defaultMountOptions = ["defaults"]  # default options passed to mount
>      _defaultLabelOptions = []
>      _defaultCheckOptions = []
>      _defaultMigrateOptions = []
> +    _defaultInfoOptions = []
>      _migrationTarget = None
> +    _existingSizeFields = []
>      lostAndFoundContext = None
>  
>      def __init__(self, *args, **kwargs):
> @@ -150,8 +154,12 @@ class FS(DeviceFormat):
>          self.mountpoint = kwargs.get("mountpoint")
>          self.mountopts = kwargs.get("mountopts")
>          self.label = kwargs.get("label")
> +
>          # filesystem size does not necessarily equal device size
>          self._size = kwargs.get("size")
> +        if self.exists:
> +            self._size = self._getExistingSize()
> +
>          self._targetSize = self._size
>          self._mountpoint = None     # the current mountpoint when mounted
>  
> @@ -187,6 +195,83 @@ class FS(DeviceFormat):
>      size = property(_getSize, doc="This filesystem's size, accounting "
>                                    "for pending changes")
>  
> +    def _getExistingSize(self):
> +        """ Determine the size of this filesystem.  Filesystem must
> +            exist.  Each filesystem varies, but the general procedure
> +            is to run the filesystem dump or info utility and read
> +            the block size and number of blocks for the filesystem
> +            and compute megabytes from that.
> +
> +            The loop that reads the output from the infofsProg is meant
> +            to be simple, but take in to account variations in output.
> +            The general procedure:
> +                1) Capture output from infofsProg.
> +                2) Iterate over each line of the output:
> +                       a) Trim leading and trailing whitespace.
> +                       b) Break line into fields split on ' '
> +                       c) If line begins with any of the strings in
> +                          _existingSizeFields, start at the end of
> +                          fields and take the first one that converts
> +                          to a long.  Store this in the values list.
> +                       d) Repeat until the values list length equals
> +                          the _existingSizeFields length.
> +                3) If the length of the values list equals the length
> +                   of _existingSizeFields, compute the size of this
> +                   filesystem by multiplying all of the values together
> +                   to get bytes, then convert to megabytes.  Return
> +                   this value.
> +                4) If we were unable to capture all fields, return 0.
> +
> +            The caller should catch exceptions from this method.  Any
> +            exception raised indicates a need to change the fields we
> +            are looking for, the command to run and arguments, or
> +            something else.  If you catch an exception from this method,
> +            assume the filesystem cannot be resized.
> +        """
> +        size = 0
> +
> +        if self.exists:
> +            values = []
> +            argv = self._defaultInfoOptions + [ self.device ]
> +
> +            buf = iutil.execWithCapture(self.infofsProg, argv,
> +                                        stderr="/dev/tty5")
> +
> +            for line in buf.splitlines():
> +                found = False
> +
> +                line = line.strip()
> +                tmp = line.split(' ')
> +                tmp.reverse()
> +
> +                for field in self._existingSizeFields:
> +                    if line.startswith(field):
> +                        for subfield in tmp:
> +                            try:
> +                                values.append(long(subfield))
> +                                found = True
> +                                break
> +                            except ValueError:
> +                                continue
> +
> +                    if found:
> +                        break
> +
> +                if len(values) == len(self._existingSizeFields):
> +                    break
> +
> +            if len(values) != len(self._existingSizeFields):
> +                return 0
> +
> +            size = 1
> +            for value in values:
> +                size *= value
> +
> +            # report current size as megabytes
> +            size = size / 1024.0 / 1024.0
> +
> +        return size
> +
>      @property
>      def currentSize(self):
>          """ The filesystem's current actual size. """
> @@ -547,13 +632,19 @@ class FS(DeviceFormat):
>          return self._migratefs
>  
>      @property
> +    def infofsProg(self):
> +        """ Program used to get information about this filesyste. """
> +        return self._infofs
> +
> +    @property
>      def migrationTarget(self):
>          return self._migrationTarget
>  
>      @property
>      def utilsAvailable(self):
>          # we aren't checking for fsck because we shouldn't need it
> -        for prog in [self.mkfsProg, self.resizefsProg, self.labelfsProg]:
> +        for prog in [self.mkfsProg, self.resizefsProg, self.labelfsProg,
> +                     self.infofsProg]:
>              if not prog:
>                  continue
>  


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]