summaryrefslogtreecommitdiffstats
path: root/storage/formats/fs.py
diff options
context:
space:
mode:
authorDavid Cantrell <dcantrell@redhat.com>2009-05-14 10:04:27 -1000
committerDavid Cantrell <dcantrell@redhat.com>2009-05-14 13:22:11 -1000
commit65ec857a9c09cb94ca9617cdc0125b765afdd0f2 (patch)
tree90e0dc89b2c55c1ea1154bc33971536387c091b7 /storage/formats/fs.py
parentf9a1864aac24bd383948b1f36f0816cd4bc79888 (diff)
downloadanaconda-65ec857a9c09cb94ca9617cdc0125b765afdd0f2.tar.gz
anaconda-65ec857a9c09cb94ca9617cdc0125b765afdd0f2.tar.xz
anaconda-65ec857a9c09cb94ca9617cdc0125b765afdd0f2.zip
Compute existing filesystem size using fs info utility.
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.
Diffstat (limited to 'storage/formats/fs.py')
-rw-r--r--storage/formats/fs.py95
1 files changed, 82 insertions, 13 deletions
diff --git a/storage/formats/fs.py b/storage/formats/fs.py
index f045a77e4..4765e653b 100644
--- a/storage/formats/fs.py
+++ b/storage/formats/fs.py
@@ -126,12 +126,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):
@@ -158,7 +161,7 @@ class FS(DeviceFormat):
self.label = kwargs.get("label")
# filesystem size does not necessarily equal device size
- self._size = kwargs.get("size")
+ self._size = kwargs.get("size", 0)
self._minInstanceSize = None # min size of this FS instance
self._mountpoint = None # the current mountpoint when mounted
if self.exists:
@@ -204,22 +207,82 @@ class FS(DeviceFormat):
def _getExistingSize(self):
""" Determine the size of this filesystem. Filesystem must
- exist.
+ 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
+ size = self._size
+
+ if self.mountable and self.exists and not size:
+ try:
+ 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()
- if self.mountable:
- origMountPoint = self._mountpoint
+ for field in self._existingSizeFields:
+ if line.startswith(field):
+ for subfield in tmp:
+ try:
+ values.append(long(subfield))
+ found = True
+ break
+ except ValueError:
+ continue
- tmppath = tempfile.mkdtemp(prefix='getsize-', dir='/tmp')
- self.mount(mountpoint=tmppath, options="ro")
- buf = os.statvfs(tmppath)
- self.unmount()
- os.rmdir(tmppath)
+ if found:
+ break
- self._mountpoint = origMountPoint
+ if len(values) == len(self._existingSizeFields):
+ break
- size = (buf.f_frsize * buf.f_blocks) / 1024.0 / 1024.0
+ 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
+ except Exception as e:
+ log.error("failed to obtain size of filesystem on %s: %s"
+ % (self.device, e))
return size
@@ -610,13 +673,19 @@ class FS(DeviceFormat):
return self._migratefs
@property
+ def infofsProg(self):
+ """ Program used to get information for this filesystem type. """
+ 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