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. --- 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@xxxxxxxxxx> +# David Cantrell <dcantrell@xxxxxxxxxx> # """ 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 -- 1.6.2 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list