This turns out to be actually quite a lot of patches about Sizes.
The first 8 patches are minor fixes for little things that I ran into while worrying about Sizes.
With "Make _Prefix entries..." I'm starting to try to set things up so that it is possible to have some kind of values that represent units to pass to convertTo() and roundToNearest(). By using string specifiers of units as arguments to these methods, we end up using _parseUnits() to find out the units. This is kind of a mistake, because it is a method that is really designed for parsing human input size strings, so it is unnecessarily heavyweight for a context where the units is precisely known and specified explicitly in the program.
"Do not even pretend..." patch is a bit of a one off. I really think we can get rid of that code, about the only thing it is likely ever to do for us is halt some install sometime (if it is ever run).
Then come three patches about resizeArgs() and _resizefsUnit. The last two of these may be somewhat controversial. Here's my take on things:
Without the "Use _resizefsUnit in resizeArgs()..." patch a developer has to have or somehow obtain some knowledge about the connection between the unit in resizeArgs() and the one in getMinSize(). Let's suppose they change _resizefsUnit (because they want to change how getMinSize() behaves). They can: (1) Fail to realize that they need to change resizeArgs() as well. If they are lucky, and they changed _resizefsUnit to a multiple of the units in resizeArgs() there may or not appear to be a problem. If they are unlucky and they changd _resizefsUnit to something other than a multiple, then the result of the resize operation will most likely be wrong. That would be a bug. (2) Realize that they need to change the units of resizeArgs() correspondingly. If so, they ought to have the good sense to look at the containing expression, and infer that they need to change the format string as well.
With the "Use _resizefsUnit in resizeArgs()..." patch a developer does not need to know any secret lore. Being conscientious, they do a search for the string _resizefsUnit and find it in resizeArgs(). They know there is a connection and only possibility (2) from above is available.
My patch eliminates the possibility of bugs arising from situation (1). I realize it relies on the programmer being able to realize that if the units of the size change, so should the format string, but I _think_ that's not hard.
Finally, there are two patches about Size.__new__. The motivation for these two is to avoid running the _parseSpec() method from Size.__new__() as _parseSpec() is really designed to handle user-input strings. It is far too general for literals specified in the program and is correspondingly busy. The locale stuff, the regular expression matching, iterating through a list dynamically calculating string specs and comparing them with the string given is huge overkill when the unit required is already known at compile time.
This approach is less invasive than some others and does not _require_ any change to user code. I think that ideally user input parsing would be handled in anaconda, since that is not really blivet's job at all, but I think that would be in the far future, so might as well do this for now.
This approach speeds construction of Size() object up by a factor of 3 or 4, suprisingly little. But it seems like the more correct thing. If everybody accepts it, I'll also convert the Size literals in tests subdirectory to use tuples.
mulhern (20): Get rid of unnecessary use of long. Make possiblePhysicalExtents() a bit more direct. Do not compare the same two values twice. Do not calculate Sizes unless they are needed. Avoid using Size constant in FileDevice._create(). Eliminate redundant test. Comment _prefixTestHelper() and eliminate some redundancies. Hoist _BINARY_FACTOR * min_value calculation out of loop. Make _Prefix entries named constants. Add unitStr() method. Make _parseUnits() return a unit constant, rather than a number. Get whole unit tuple in loop when searching for correct units. Do not even pretend that ReiserFS is resizable. Change convertTo() and roundToNearest() so each takes a units specifier. Use convertTo in humanReadable(). Do not supply a default implementation for the resizeArgs() method. Use _resizefsUnit in resizeArgs() method implementations. Add _resizefsUnit to TmpFS and use in appropriate places. Add a new way of specifying Sizes(). Use tuples to construct Sizes() wherever units are known.
blivet/devicefactory.py | 6 +- blivet/devicelibs/btrfs.py | 4 +- blivet/devicelibs/crypto.py | 4 +- blivet/devicelibs/lvm.py | 45 +++++----- blivet/devicelibs/mdraid.py | 10 +-- blivet/devicelibs/swap.py | 15 ++-- blivet/devices/file.py | 8 +- blivet/devices/lvm.py | 16 ++-- blivet/devices/partition.py | 12 +-- blivet/formats/biosboot.py | 6 +- blivet/formats/fs.py | 77 ++++++++--------- blivet/formats/prepboot.py | 6 +- blivet/formats/swap.py | 4 +- blivet/partitioning.py | 6 +- blivet/platform.py | 22 ++--- blivet/size.py | 168 ++++++++++++++++++++------------------ blivet/udev.py | 12 +-- blivet/util.py | 6 +- tests/devicelibs_test/lvm_test.py | 5 -- tests/size_test.py | 96 +++++++++++----------- tests/storagetestcase.py | 4 +- 21 files changed, 261 insertions(+), 271 deletions(-)
Python 2.7 will do all the necessary conversion to long if required. Get rid of Python 3 compatibility stuff as well.
This is the last of explicit use of long in blivet.
Signed-off-by: mulhern amulhern@redhat.com --- tests/size_test.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/tests/size_test.py b/tests/size_test.py index c587ee0..25cda3f 100644 --- a/tests/size_test.py +++ b/tests/size_test.py @@ -27,16 +27,11 @@ import unittest
from decimal import Decimal
-import six - from blivet.i18n import _ from blivet.errors import SizePlacesError from blivet import size from blivet.size import Size, _EMPTY_PREFIX, _BINARY_PREFIXES, _DECIMAL_PREFIXES
-if six.PY3: - long = int # pylint: disable=redefined-builtin - class SizeTestCase(unittest.TestCase):
def testExceptions(self): @@ -73,17 +68,17 @@ class SizeTestCase(unittest.TestCase): self.assertEquals(s.convertTo(), numbytes)
def testPrefixes(self): - numbytes = long(47) + numbytes = 47 self._prefixTestHelper(numbytes, 1, None, None)
for factor, prefix, abbr in [_EMPTY_PREFIX] + _BINARY_PREFIXES + _DECIMAL_PREFIXES: self._prefixTestHelper(numbytes, factor, prefix, abbr)
def testHumanReadable(self): - s = Size(long(58929971)) + s = Size(58929971) self.assertEquals(s.humanReadable(), "56.2 MiB")
- s = Size(long(478360371)) + s = Size(478360371) self.assertEquals(s.humanReadable(), "456.2 MiB")
# humanReable output should be the same as input for big enough sizes
Remove corresponding tests because now it just duplicates the code except where it uses xrange (which is missing from Python3).
Signed-off-by: mulhern amulhern@redhat.com --- blivet/devicelibs/lvm.py | 9 +-------- tests/devicelibs_test/lvm_test.py | 5 ----- 2 files changed, 1 insertion(+), 13 deletions(-)
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py index 1bf87fa..3559dab 100644 --- a/blivet/devicelibs/lvm.py +++ b/blivet/devicelibs/lvm.py @@ -129,14 +129,7 @@ def getPossiblePhysicalExtents(): :returns: list of possible extent sizes (:class:`~.size.Size`) :rtype: list """ - - possiblePE = [] - curpe = Size("1 KiB") - while curpe <= Size("16 GiB"): - possiblePE.append(curpe) - curpe = curpe * 2 - - return possiblePE + return [Size(1024 * (2 ** n)) for n in range(25)]
def getMaxLVSize(): """ Return the maximum size of a logical volume. """ diff --git a/tests/devicelibs_test/lvm_test.py b/tests/devicelibs_test/lvm_test.py index 5518f16..6fc81fd 100755 --- a/tests/devicelibs_test/lvm_test.py +++ b/tests/devicelibs_test/lvm_test.py @@ -12,11 +12,6 @@ from tests import loopbackedtestcase
class LVMTestCase(unittest.TestCase):
- def testGetPossiblePhysicalExtents(self): - # pass - self.assertEqual(lvm.getPossiblePhysicalExtents(), - [Size("%d KiB" % 2**power) for power in xrange(0, 25)]) - def testClampSize(self): # pass self.assertEqual(lvm.clampSize(Size("10 MiB"), Size("4 MiB")),
If x and y are Sizes, not (x < y) implies x >= y.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/devicelibs/swap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/devicelibs/swap.py b/blivet/devicelibs/swap.py index bcc0308..4e31cdb 100644 --- a/blivet/devicelibs/swap.py +++ b/blivet/devicelibs/swap.py @@ -146,10 +146,10 @@ def swapSuggestion(quiet=False, hibernation=False, disk_space=None): if mem < two_GiB: swap = 2 * mem
- elif two_GiB <= mem < eight_GiB: + elif mem < eight_GiB: swap = mem
- elif eight_GiB <= mem < sixtyfour_GiB: + elif mem < sixtyfour_GiB: swap = mem / 2
else:
On Tue, 2014-12-23 at 18:42 -0500, mulhern wrote:
If x and y are Sizes, not (x < y) implies x >= y.
Signed-off-by: mulhern amulhern@redhat.com
blivet/devicelibs/swap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/devicelibs/swap.py b/blivet/devicelibs/swap.py index bcc0308..4e31cdb 100644 --- a/blivet/devicelibs/swap.py +++ b/blivet/devicelibs/swap.py @@ -146,10 +146,10 @@ def swapSuggestion(quiet=False, hibernation=False, disk_space=None): if mem < two_GiB: swap = 2 * mem
- elif two_GiB <= mem < eight_GiB:
- elif mem < eight_GiB: swap = mem
- elif eight_GiB <= mem < sixtyfour_GiB:
- elif mem < sixtyfour_GiB: swap = mem / 2
The condition was intentionally written like this to be as clear and nice readable as possible because it is quite often target of people outside of our team. I don't think we need to optimize this code.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/devicelibs/swap.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/blivet/devicelibs/swap.py b/blivet/devicelibs/swap.py index 4e31cdb..28c8d2a 100644 --- a/blivet/devicelibs/swap.py +++ b/blivet/devicelibs/swap.py @@ -137,23 +137,20 @@ def swapSuggestion(quiet=False, hibernation=False, disk_space=None): if not quiet: log.info("Detected %s of memory", mem)
- two_GiB = Size("2GiB") - four_GiB = Size("4GiB") - eight_GiB = Size("8GiB") sixtyfour_GiB = Size("64 GiB")
#chart suggested in the discussion with other teams - if mem < two_GiB: + if mem < Size("2 GiB"): swap = 2 * mem
- elif mem < eight_GiB: + elif mem < Size("8 GiB"): swap = mem
elif mem < sixtyfour_GiB: swap = mem / 2
else: - swap = four_GiB + swap = Size("4 GiB")
if hibernation: if mem <= sixtyfour_GiB:
It makes the code a little bit awkward and busy and the name MiB will conflict with some size constants defined in subsequent patch. New code is an order of magnitude more efficient, which is a bonus.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/devices/file.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/blivet/devices/file.py b/blivet/devices/file.py index da231c5..628853d 100644 --- a/blivet/devices/file.py +++ b/blivet/devices/file.py @@ -24,7 +24,6 @@ import os
from .. import util from ..storage_log import log_method_call -from ..size import Size
import logging log = logging.getLogger("blivet") @@ -98,12 +97,11 @@ class FileDevice(StorageDevice): fd = os.open(self.path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC) # all this fuss is so we write the zeros 1MiB at a time zero = "\0" - MiB = Size("1 MiB") - count = int(self.size.convertTo(spec="MiB")) - rem = self.size % MiB + block_size = 1024 ** 2 + (count, rem) = divmod(int(self.size), block_size)
for _n in range(count): - os.write(fd, zero * MiB) + os.write(fd, zero * block_size)
if rem: # write out however many more zeros it takes to hit our size target
On Tue, 2014-12-23 at 18:42 -0500, mulhern wrote:
It makes the code a little bit awkward and busy and the name MiB will conflict with some size constants defined in subsequent patch. New code is an order of magnitude more efficient, which is a bonus.
Signed-off-by: mulhern amulhern@redhat.com
blivet/devices/file.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/blivet/devices/file.py b/blivet/devices/file.py index da231c5..628853d 100644 --- a/blivet/devices/file.py +++ b/blivet/devices/file.py @@ -24,7 +24,6 @@ import os
from .. import util from ..storage_log import log_method_call -from ..size import Size
import logging log = logging.getLogger("blivet") @@ -98,12 +97,11 @@ class FileDevice(StorageDevice): fd = os.open(self.path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC) # all this fuss is so we write the zeros 1MiB at a time zero = "\0"
MiB = Size("1 MiB")count = int(self.size.convertTo(spec="MiB"))rem = self.size % MiB
block_size = 1024 ** 2(count, rem) = divmod(int(self.size), block_size) for _n in range(count):
os.write(fd, zero * MiB)
os.write(fd, zero * block_size)
Is it really wise to allocate 1 MiB chunk of memory full of zeroes only to write it out to a file?
----- Original Message -----
From: "Vratislav Podzimek" vpodzime@redhat.com To: "anaconda patch review" anaconda-patches@lists.fedorahosted.org Sent: Monday, January 5, 2015 2:51:36 AM Subject: Re: [blivet:master 05/20] Avoid using Size constant in FileDevice._create().
On Tue, 2014-12-23 at 18:42 -0500, mulhern wrote:
It makes the code a little bit awkward and busy and the name MiB will conflict with some size constants defined in subsequent patch. New code is an order of magnitude more efficient, which is a bonus.
Signed-off-by: mulhern amulhern@redhat.com
blivet/devices/file.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/blivet/devices/file.py b/blivet/devices/file.py index da231c5..628853d 100644 --- a/blivet/devices/file.py +++ b/blivet/devices/file.py @@ -24,7 +24,6 @@ import os
from .. import util from ..storage_log import log_method_call -from ..size import Size
import logging log = logging.getLogger("blivet") @@ -98,12 +97,11 @@ class FileDevice(StorageDevice): fd = os.open(self.path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC) # all this fuss is so we write the zeros 1MiB at a time zero = "\0"
MiB = Size("1 MiB")count = int(self.size.convertTo(spec="MiB"))rem = self.size % MiB
block_size = 1024 ** 2(count, rem) = divmod(int(self.size), block_size) for _n in range(count):
os.write(fd, zero * MiB)
os.write(fd, zero * block_size)Is it really wise to allocate 1 MiB chunk of memory full of zeroes only to write it out to a file?
-- Vratislav Podzimek
Anaconda Rider | Red Hat, Inc. | Brno - Czech Republic
anaconda-patches mailing list anaconda-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
Nope, it's not. I've extended the patch to hoist zero * block_size computation above loop.
- mulhern
On Mon, 2015-01-05 at 07:49 -0500, Anne Mulhern wrote:
----- Original Message -----
From: "Vratislav Podzimek" vpodzime@redhat.com To: "anaconda patch review" anaconda-patches@lists.fedorahosted.org Sent: Monday, January 5, 2015 2:51:36 AM Subject: Re: [blivet:master 05/20] Avoid using Size constant in FileDevice._create().
On Tue, 2014-12-23 at 18:42 -0500, mulhern wrote:
It makes the code a little bit awkward and busy and the name MiB will conflict with some size constants defined in subsequent patch. New code is an order of magnitude more efficient, which is a bonus.
Signed-off-by: mulhern amulhern@redhat.com
blivet/devices/file.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/blivet/devices/file.py b/blivet/devices/file.py index da231c5..628853d 100644 --- a/blivet/devices/file.py +++ b/blivet/devices/file.py @@ -24,7 +24,6 @@ import os
from .. import util from ..storage_log import log_method_call -from ..size import Size
import logging log = logging.getLogger("blivet") @@ -98,12 +97,11 @@ class FileDevice(StorageDevice): fd = os.open(self.path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC) # all this fuss is so we write the zeros 1MiB at a time zero = "\0"
MiB = Size("1 MiB")count = int(self.size.convertTo(spec="MiB"))rem = self.size % MiB
block_size = 1024 ** 2(count, rem) = divmod(int(self.size), block_size) for _n in range(count):
os.write(fd, zero * MiB)
os.write(fd, zero * block_size)Is it really wise to allocate 1 MiB chunk of memory full of zeroes only to write it out to a file?
-- Vratislav Podzimek
Anaconda Rider | Red Hat, Inc. | Brno - Czech Republic
anaconda-patches mailing list anaconda-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
Nope, it's not. I've extended the patch to hoist zero * block_size computation above loop.
That's what I meant. Thanks!
The test is done in the loop below, it does not need to be run twice.
Signed-off-by: mulhern amulhern@redhat.com --- tests/size_test.py | 1 - 1 file changed, 1 deletion(-)
diff --git a/tests/size_test.py b/tests/size_test.py index 25cda3f..4a49cc7 100644 --- a/tests/size_test.py +++ b/tests/size_test.py @@ -69,7 +69,6 @@ class SizeTestCase(unittest.TestCase):
def testPrefixes(self): numbytes = 47 - self._prefixTestHelper(numbytes, 1, None, None)
for factor, prefix, abbr in [_EMPTY_PREFIX] + _BINARY_PREFIXES + _DECIMAL_PREFIXES: self._prefixTestHelper(numbytes, factor, prefix, abbr)
The checks for prefix, abbr are unnecessary, since _makeSpec will do the correct thing if either is the empty string.
Signed-off-by: mulhern amulhern@redhat.com --- tests/size_test.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/tests/size_test.py b/tests/size_test.py index 4a49cc7..1ec7fbd 100644 --- a/tests/size_test.py +++ b/tests/size_test.py @@ -44,28 +44,28 @@ class SizeTestCase(unittest.TestCase):
self.assertEqual(s.humanReadable(max_places=0), "500 B")
- def _prefixTestHelper(self, numbytes, factor, prefix, abbr): - c = numbytes * factor + def _prefixTestHelper(self, numunits, factor, prefix, abbr): + """ Test that units and prefix or abbreviation agree. + + :param int numunits: this value times factor yields number of bytes + :param int factor: this value times numunits yields number of bytes + :param str prefix: the prefix used to specify the units + :param str abbr: the abbreviation used to specify the units + """ + c = numunits * factor
s = Size(c) self.assertEquals(s, Size(c))
- if prefix: - u = "%sbytes" % prefix - s = Size("%ld %s" % (numbytes, u)) - self.assertEquals(s, c) - self.assertEquals(s.convertTo(spec=u), numbytes) - - if abbr: - u = "%sb" % abbr - s = Size("%ld %s" % (numbytes, u)) - self.assertEquals(s, c) - self.assertEquals(s.convertTo(spec=u), numbytes) - - if not prefix and not abbr: - s = Size("%ld" % numbytes) - self.assertEquals(s, c) - self.assertEquals(s.convertTo(), numbytes) + u = size._makeSpec(prefix, size._BYTES_WORDS[0], False) + s = Size("%ld %s" % (numunits, u)) + self.assertEquals(s, c) + self.assertEquals(s.convertTo(spec=u), numunits) + + u = size._makeSpec(abbr, size._BYTES_SYMBOL, False) + s = Size("%ld %s" % (numunits, u)) + self.assertEquals(s, c) + self.assertEquals(s.convertTo(spec=u), numunits)
def testPrefixes(self): numbytes = 47
Signed-off-by: mulhern amulhern@redhat.com --- blivet/size.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/blivet/size.py b/blivet/size.py index 6d24fdf..697f5b3 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -348,10 +348,11 @@ class Size(Decimal): # _BINARY_FACTOR * min_value to the left of the decimal point. # If the number is so large that no prefix will satisfy this # requirement use the largest prefix. + limit = _BINARY_FACTOR * min_value for factor, _prefix, abbr in [_EMPTY_PREFIX] + _BINARY_PREFIXES: newcheck = super(Size, self).__div__(Decimal(factor))
- if abs(newcheck) < _BINARY_FACTOR * min_value: + if abs(newcheck) < limit: # nice value, use this factor, prefix and abbr break
They can be useful as arguments for methods.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/size.py | 54 +++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 29 deletions(-)
diff --git a/blivet/size.py b/blivet/size.py index 697f5b3..a09c277 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -44,35 +44,31 @@ _BINARY_FACTOR = 2 ** 10 _BYTES_SYMBOL = N_(b"B") _BYTES_WORDS = (N_(b"bytes"), N_(b"byte"))
-# Decimal prefixes for different size increments, along with the name -# and accepted abbreviation for the prefix. These prefixes are all -# for 'bytes'. -_DECIMAL_PREFIXES = [ - _Prefix(_DECIMAL_FACTOR ** 1, N_(b"kilo"), N_(b"k")), - _Prefix(_DECIMAL_FACTOR ** 2, N_(b"mega"), N_(b"M")), - _Prefix(_DECIMAL_FACTOR ** 3, N_(b"giga"), N_(b"G")), - _Prefix(_DECIMAL_FACTOR ** 4, N_(b"tera"), N_(b"T")), - _Prefix(_DECIMAL_FACTOR ** 5, N_(b"peta"), N_(b"P")), - _Prefix(_DECIMAL_FACTOR ** 6, N_(b"exa"), N_(b"E")), - _Prefix(_DECIMAL_FACTOR ** 7, N_(b"zetta"), N_(b"Z")), - _Prefix(_DECIMAL_FACTOR ** 8, N_(b"yotta"), N_(b"Y")) -] - -# Binary prefixes for the different size increments. Same structure -# as the above list. -_BINARY_PREFIXES = [ - _Prefix(_BINARY_FACTOR ** 1, N_(b"kibi"), N_(b"Ki")), - _Prefix(_BINARY_FACTOR ** 2, N_(b"mebi"), N_(b"Mi")), - _Prefix(_BINARY_FACTOR ** 3, N_(b"gibi"), N_(b"Gi")), - _Prefix(_BINARY_FACTOR ** 4, N_(b"tebi"), N_(b"Ti")), - _Prefix(_BINARY_FACTOR ** 5, N_(b"pebi"), N_(b"Pi")), - _Prefix(_BINARY_FACTOR ** 6, N_(b"exbi"), N_(b"Ei")), - _Prefix(_BINARY_FACTOR ** 7, N_(b"zebi"), N_(b"Zi")), - _Prefix(_BINARY_FACTOR ** 8, N_(b"yobi"), N_(b"Yi")) -] - -# Empty prefix works both for decimal and binary -_EMPTY_PREFIX = _Prefix(1, b"", b"") +# Symbolic constants for units +B = _Prefix(1, b"", b"") + +KB = _Prefix(_DECIMAL_FACTOR ** 1, N_(b"kilo"), N_(b"k")) +MB = _Prefix(_DECIMAL_FACTOR ** 2, N_(b"mega"), N_(b"M")) +GB = _Prefix(_DECIMAL_FACTOR ** 3, N_(b"giga"), N_(b"G")) +TB = _Prefix(_DECIMAL_FACTOR ** 4, N_(b"tera"), N_(b"T")) +PB = _Prefix(_DECIMAL_FACTOR ** 5, N_(b"peta"), N_(b"P")) +EB = _Prefix(_DECIMAL_FACTOR ** 6, N_(b"exa"), N_(b"E")) +ZB = _Prefix(_DECIMAL_FACTOR ** 7, N_(b"zetta"), N_(b"Z")) +YB = _Prefix(_DECIMAL_FACTOR ** 8, N_(b"yotta"), N_(b"Y")) + +KiB = _Prefix(_BINARY_FACTOR ** 1, N_(b"kibi"), N_(b"Ki")) +MiB = _Prefix(_BINARY_FACTOR ** 2, N_(b"mebi"), N_(b"Mi")) +GiB = _Prefix(_BINARY_FACTOR ** 3, N_(b"gibi"), N_(b"Gi")) +TiB = _Prefix(_BINARY_FACTOR ** 4, N_(b"tebi"), N_(b"Ti")) +PiB = _Prefix(_BINARY_FACTOR ** 5, N_(b"pebi"), N_(b"Pi")) +EiB = _Prefix(_BINARY_FACTOR ** 6, N_(b"exbi"), N_(b"Ei")) +ZiB = _Prefix(_BINARY_FACTOR ** 7, N_(b"zebi"), N_(b"Zi")) +YiB = _Prefix(_BINARY_FACTOR ** 8, N_(b"yobi"), N_(b"Yi")) + +# Categories of symbolic constants +_DECIMAL_PREFIXES = [KB, MB, GB, TB, PB, EB, ZB, YB] +_BINARY_PREFIXES = [KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB] +_EMPTY_PREFIX = B
if six.PY2: _ASCIIlower_table = string.maketrans(string.ascii_uppercase, string.ascii_lowercase) # pylint: disable=no-member
Signed-off-by: mulhern amulhern@redhat.com --- blivet/size.py | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/blivet/size.py b/blivet/size.py index a09c277..79564c2 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -105,6 +105,16 @@ def _makeSpec(prefix, suffix, xlate, lowercase=True): word = prefix + suffix return _lowerASCII(word) if lowercase else word
+def unitStr(unit, xlate=False): + """ Return a string representation of unit. + + :param unit: a named unit, e.g., KiB + :param bool xlate: if True, translate to current locale + :rtype: some kind of string type + :returns: string representation of unit + """ + return _makeSpec(unit.abbr, _BYTES_SYMBOL, xlate, lowercase=False) + def _parseUnits(units, xlate): """ Parse a unit specification and return corresponding factor.
Update client code appropriately.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/size.py | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/blivet/size.py b/blivet/size.py index 79564c2..cdf22b2 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -115,39 +115,39 @@ def unitStr(unit, xlate=False): """ return _makeSpec(unit.abbr, _BYTES_SYMBOL, xlate, lowercase=False)
-def _parseUnits(units, xlate): +def _parseUnits(spec, xlate): """ Parse a unit specification and return corresponding factor.
- :param units: a units specifier - :type units: any type of string like object + :param spec: a units specifier + :type spec: any type of string like object :param bool xlate: if True, assume locale specific
- :returns: a numeric factor corresponding to the units, if found - :rtype: int or NoneType + :returns: a named constant corresponding to spec, if found + :rtype: _Prefix or NoneType
Looks first for exact matches for a specifier, but, failing that, searches for partial matches for abbreviations.
Normalizes units to lowercase, e.g., MiB and mib are treated the same. """ - if units == "": - return 1 + if spec == "": + return B
if xlate: - units = units.lower() + spec = spec.lower() else: - units = _lowerASCII(units) + spec = _lowerASCII(spec)
# Search for complete matches - for factor, prefix, abbr in [_EMPTY_PREFIX] + _BINARY_PREFIXES + _DECIMAL_PREFIXES: - if units == _makeSpec(abbr, _BYTES_SYMBOL, xlate) or \ - units in (_makeSpec(prefix, s, xlate) for s in _BYTES_WORDS): - return factor + for unit in [_EMPTY_PREFIX] + _BINARY_PREFIXES + _DECIMAL_PREFIXES: + if spec == _makeSpec(unit.abbr, _BYTES_SYMBOL, xlate) or \ + spec in (_makeSpec(unit.prefix, s, xlate) for s in _BYTES_WORDS): + return unit
# Search for unambiguous partial match among binary abbreviations - matches = [p for p in _BINARY_PREFIXES if _makeSpec(p.abbr, "", xlate).startswith(units)] + matches = [p for p in _BINARY_PREFIXES if _makeSpec(p.abbr, "", xlate).startswith(spec)] if len(matches) == 1: - return matches[0].factor + return matches[0]
return None
@@ -197,9 +197,9 @@ def _parseSpec(spec): # String contains non-ascii characters, so can not be English. pass else: - factor = _parseUnits(spec_ascii, False) - if factor is not None: - return size * factor + unit = _parseUnits(spec_ascii, False) + if unit is not None: + return size * unit.factor
# No English match found, try localized size specs. if six.PY2: @@ -210,9 +210,9 @@ def _parseSpec(spec): else: spec_local = specifier
- factor = _parseUnits(spec_local, True) - if factor is not None: - return size * factor + unit = _parseUnits(spec_local, True) + if unit is not None: + return size * unit.factor
raise ValueError("invalid size specification", spec)
@@ -301,9 +301,9 @@ class Size(Decimal): :returns: a numeric value in the units indicated by the specifier :rtype: Decimal """ - divisor = _parseUnits(spec, xlate) - if divisor: - return Decimal(self) / Decimal(divisor) + unit = _parseUnits(spec, xlate) + if unit: + return Decimal(self) / Decimal(unit.factor)
return None
Some parts of the tuple are not used. This way, it is unnecessary to name them and then ignore them.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/size.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/blivet/size.py b/blivet/size.py index cdf22b2..f37a873 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -355,11 +355,10 @@ class Size(Decimal): # If the number is so large that no prefix will satisfy this # requirement use the largest prefix. limit = _BINARY_FACTOR * min_value - for factor, _prefix, abbr in [_EMPTY_PREFIX] + _BINARY_PREFIXES: - newcheck = super(Size, self).__div__(Decimal(factor)) + for unit in [_EMPTY_PREFIX] + _BINARY_PREFIXES: + newcheck = super(Size, self).__div__(Decimal(unit.factor))
if abs(newcheck) < limit: - # nice value, use this factor, prefix and abbr break
if max_places is not None: @@ -376,7 +375,7 @@ class Size(Decimal): retval_str = retval_str.replace('.', radix)
# pylint: disable=undefined-loop-variable - return retval_str + " " + _makeSpec(abbr, _BYTES_SYMBOL, xlate, lowercase=False) + return retval_str + " " + _makeSpec(unit.abbr, _BYTES_SYMBOL, xlate, lowercase=False)
def roundToNearest(self, unit, rounding=ROUND_DEFAULT): """
To a resize request it will timidly respond:
resize_reiserfs 3.6.24
You are running BETA version of reiserfs shrinker. This version is only for testing or VERY CAREFUL use. Backup of you data is recommended.
Do you want to continue? [y/N]:
In man page, there is described a flag:
-f Force, do not perform checks.
but no amount of -f'ing will persuade resize_reiserfs to just do it.
This is true not just in the currently distributed f20 version (3.6.21), but also in the most recent version, 3.6.24.
ReiserFS is fairly moribund, I don't think this state of affairs is likely to change.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/formats/fs.py | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 07a383a..55da105 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1238,7 +1238,6 @@ class ReiserFS(FS): """ reiserfs filesystem """ _type = "reiserfs" _mkfs = "mkreiserfs" - _resizefs = "resize_reiserfs" _labelfs = fslabeling.ReiserFSLabeling() _modules = ["reiserfs"] _defaultFormatOptions = ["-f", "-f"] @@ -1261,11 +1260,6 @@ class ReiserFS(FS):
return supported
- @property - def resizeArgs(self): - argv = ["-s", "%dM" % (self.targetSize.convertTo(spec="MiB"),), self.device] - return argv - register_device_format(ReiserFS)
It's a lot nicer to pass them a named constant that they can use directly, rather than a spec, which must be parsed as if it was entered by a user.
If there is ever a situation where the target of the conversion is user specified, there is always _parseUnit() for converting a string to a unit.
Get rid of xlate parameter on convertTo(), it's pointless if the spec is no longer being passed.
Change calling code appropriately.
This change requires a corresponding change in anaconda as convertTo() is called there in two places.
The gains are clarity, simplicity, and efficiency.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/devicelibs/lvm.py | 20 +++++++------- blivet/devices/lvm.py | 16 ++++++------ blivet/devices/partition.py | 8 +++--- blivet/formats/fs.py | 20 +++++++------- blivet/size.py | 14 ++++------ tests/size_test.py | 64 ++++++++++++++++++++++----------------------- tests/storagetestcase.py | 4 ++- 7 files changed, 71 insertions(+), 75 deletions(-)
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py index 3559dab..ce576e2 100644 --- a/blivet/devicelibs/lvm.py +++ b/blivet/devicelibs/lvm.py @@ -27,7 +27,7 @@ import logging log = logging.getLogger("blivet")
from . import raid -from ..size import Size +from ..size import Size, KiB, MiB from .. import util from .. import arch from ..errors import LVMError @@ -245,7 +245,7 @@ def pvcreate(device):
def pvresize(device, size): args = ["pvresize", - "--setphysicalvolumesize", ("%dm" % size.convertTo(spec="mib")), + "--setphysicalvolumesize", ("%dm" % size.convertTo(MiB)), device]
try: @@ -340,7 +340,7 @@ def pvinfo(device=None): def vgcreate(vg_name, pv_list, pe_size): argv = ["vgcreate"] if pe_size: - argv.extend(["-s", "%dm" % pe_size.convertTo(spec="mib")]) + argv.extend(["-s", "%dm" % pe_size.convertTo(MiB)]) argv.append(vg_name) argv.extend(pv_list)
@@ -478,7 +478,7 @@ def lvcreate(vg_name, lv_name, size, pvs=None): pvs = pvs or []
args = ["lvcreate"] + \ - ["-L", "%dm" % size.convertTo(spec="mib")] + \ + ["-L", "%dm" % size.convertTo(MiB)] + \ ["-n", lv_name] + \ ["-y"] + \ [vg_name] + pvs @@ -502,7 +502,7 @@ def lvremove(vg_name, lv_name, force=False):
def lvresize(vg_name, lv_name, size): args = ["lvresize"] + \ - ["--force", "-L", "%dm" % size.convertTo(spec="mib")] + \ + ["--force", "-L", "%dm" % size.convertTo(MiB)] + \ ["%s/%s" % (vg_name, lv_name)]
try: @@ -555,7 +555,7 @@ def lvsnapshotcreate(vg_name, snap_name, size, origin_name): :param :class:`~.size.Size` size: the snapshot's size :param str origin_name: the name of the origin logical volume """ - args = ["lvcreate", "-s", "-L", "%dm" % size.convertTo(spec="MiB"), + args = ["lvcreate", "-s", "-L", "%dm" % size.convertTo(MiB), "-n", snap_name, "%s/%s" % (vg_name, origin_name)]
try: @@ -565,15 +565,15 @@ def lvsnapshotcreate(vg_name, snap_name, size, origin_name):
def thinpoolcreate(vg_name, lv_name, size, metadatasize=None, chunksize=None, profile=None): args = ["lvcreate", "--thinpool", "%s/%s" % (vg_name, lv_name), - "--size", "%dm" % size.convertTo(spec="mib")] + "--size", "%dm" % size.convertTo(MiB)]
if metadatasize: # default unit is MiB - args += ["--poolmetadatasize", "%d" % metadatasize.convertTo(spec="mib")] + args += ["--poolmetadatasize", "%d" % metadatasize.convertTo(MiB)]
if chunksize: # default unit is KiB - args += ["--chunksize", "%d" % chunksize.convertTo(spec="kib")] + args += ["--chunksize", "%d" % chunksize.convertTo(KiB)]
if profile: args += ["--profile=%s" % profile] @@ -585,7 +585,7 @@ def thinpoolcreate(vg_name, lv_name, size, metadatasize=None, chunksize=None, pr
def thinlvcreate(vg_name, pool_name, lv_name, size): args = ["lvcreate", "--thinpool", "%s/%s" % (vg_name, pool_name), - "--virtualsize", "%dm" % size.convertTo(spec="MiB"), + "--virtualsize", "%dm" % size.convertTo(MiB), "-n", lv_name]
try: diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py index 3dd77de..d1817dd 100644 --- a/blivet/devices/lvm.py +++ b/blivet/devices/lvm.py @@ -34,7 +34,7 @@ from .. import util from ..formats import getFormat from ..storage_log import log_method_call from .. import udev -from ..size import Size +from ..size import Size, KiB, MiB
import logging log = logging.getLogger("blivet") @@ -411,7 +411,7 @@ class LVMVolumeGroupDevice(ContainerDevice): data.physvols = ["pv.%d" % p.id for p in self.parents] data.preexist = self.exists if not self.exists: - data.pesize = self.peSize.convertTo(spec="KiB") + data.pesize = self.peSize.convertTo(KiB)
# reserved percent/space
@@ -752,14 +752,14 @@ class LVMLogicalVolumeDevice(DMDevice): if not self.exists: data.grow = self.req_grow if self.req_grow: - data.size = self.req_size.convertTo(spec="MiB") - data.maxSizeMB = self.req_max_size.convertTo(spec="MiB") + data.size = self.req_size.convertTo(MiB) + data.maxSizeMB = self.req_max_size.convertTo(MiB) else: - data.size = self.size.convertTo(spec="MiB") + data.size = self.size.convertTo(MiB)
data.percent = self.req_percent elif data.resize: - data.size = self.targetSize.convertTo(spec="MiB") + data.size = self.targetSize.convertTo(MiB)
@classmethod def isNameValid(cls, name): @@ -1085,8 +1085,8 @@ class LVMThinPoolDevice(LVMLogicalVolumeDevice): super(LVMThinPoolDevice, self).populateKSData(data) data.mountpoint = "none" data.thin_pool = True - data.metadata_size = self.metaDataSize.convertTo(spec="MiB") - data.chunk_size = self.chunkSize.convertTo(spec="KiB") + data.metadata_size = self.metaDataSize.convertTo(MiB) + data.chunk_size = self.chunkSize.convertTo(KiB) if self.profile: data.profile = self.profile.name
diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py index 24f85b3..be42de5 100644 --- a/blivet/devices/partition.py +++ b/blivet/devices/partition.py @@ -30,7 +30,7 @@ from ..flags import flags from ..storage_log import log_method_call from .. import udev from ..formats import DeviceFormat, getFormat -from ..size import Size +from ..size import Size, MiB
from ..devicelibs import dm
@@ -842,10 +842,10 @@ class PartitionDevice(StorageDevice): data.resize = (self.exists and self.targetSize and self.targetSize != self.currentSize) if not self.exists: - data.size = self.req_base_size.convertTo(spec="MiB") + data.size = self.req_base_size.convertTo(MiB) data.grow = self.req_grow if self.req_grow: - data.maxSizeMB = self.req_max_size.convertTo(spec="MiB") + data.maxSizeMB = self.req_max_size.convertTo(MiB)
##data.disk = self.disk.name # by-id if self.req_disks and len(self.req_disks) == 1: @@ -855,4 +855,4 @@ class PartitionDevice(StorageDevice): data.onPart = self.name # by-id
if data.resize: - data.size = self.size.convertTo(spec="MiB") + data.size = self.size.convertTo(MiB) diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 55da105..e09d1e5 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -35,7 +35,7 @@ from ..flags import flags from parted import fileSystemType from ..storage_log import log_exception_info, log_method_call from .. import arch -from ..size import Size, ROUND_UP, ROUND_DOWN +from ..size import Size, ROUND_UP, ROUND_DOWN, MiB, B, unitStr from ..i18n import _, N_ from .. import udev
@@ -431,7 +431,7 @@ class FS(DeviceFormat):
@property def resizeArgs(self): - argv = [self.device, "%d" % (self.targetSize.convertTo("MiB"),)] + argv = [self.device, "%d" % (self.targetSize.convertTo(MiB),)] return argv
def doResize(self): @@ -495,7 +495,7 @@ class FS(DeviceFormat): # early. if self.targetSize > self.currentSize and rounded < self.currentSize: log.info("rounding target size down to next %s obviated resize of " - "filesystem on %s", self._resizefsUnit, self.device) + "filesystem on %s", unitStr(self._resizefsUnit), self.device) return else: self.targetSize = rounded @@ -942,7 +942,7 @@ class Ext2FS(FS): _infofs = "dumpe2fs" _defaultInfoOptions = ["-h"] _existingSizeFields = ["Block count:", "Block size:"] - _resizefsUnit = "MiB" + _resizefsUnit = MiB _fsProfileSpecifier = "-T" partedSystem = fileSystemType["ext2"]
@@ -1041,7 +1041,7 @@ class Ext2FS(FS):
@property def resizeArgs(self): - argv = ["-p", self.device, "%dM" % (self.targetSize.convertTo("MiB"))] + argv = ["-p", self.device, "%dM" % (self.targetSize.convertTo(MiB))] return argv
register_device_format(Ext2FS) @@ -1383,7 +1383,7 @@ class NTFS(FS): _infofs = "ntfsinfo" _defaultInfoOptions = ["-m"] _existingSizeFields = ["Cluster Size:", "Volume Size in Clusters:"] - _resizefsUnit = "B" + _resizefsUnit = B partedSystem = fileSystemType["ntfs"]
def _fsckFailed(self, rc): @@ -1440,7 +1440,7 @@ class NTFS(FS): def resizeArgs(self): # You must supply at least two '-f' options to ntfsresize or # the proceed question will be presented to you. - argv = ["-ff", "-s", "%d" % self.targetSize.convertTo(spec="b"), + argv = ["-ff", "-s", "%d" % self.targetSize.convertTo(B), self.device] return argv
@@ -1587,7 +1587,7 @@ class TmpFS(NoDevFS): self._options = fsoptions if self._size: # absolute size for the tmpfs mount has been specified - self._size_option = "size=%dm" % self._size.convertTo(spec="MiB") + self._size_option = "size=%dm" % self._size.convertTo(MiB) else: # if no size option is specified, the tmpfs mount size will be 50% # of system RAM by default @@ -1669,7 +1669,7 @@ class TmpFS(NoDevFS): # the mount command
# add the remount flag, size and any options - remount_options = 'remount,size=%dm' % self.targetSize.convertTo(spec="MiB") + remount_options = 'remount,size=%dm' % self.targetSize.convertTo(MiB) # if any mount options are defined, append them if self._options: remount_options = "%s,%s" % (remount_options, self._options) @@ -1689,7 +1689,7 @@ class TmpFS(NoDevFS): # update the size option string # -> please note that resizing always sets the # size of this tmpfs mount to an absolute value - self._size_option = "size=%dm" % self._size.convertTo(spec="MiB") + self._size_option = "size=%dm" % self._size.convertTo(MiB)
register_device_format(TmpFS)
diff --git a/blivet/size.py b/blivet/size.py index f37a873..2275b22 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -294,18 +294,14 @@ class Size(Decimal): def __mod__(self, other, context=None): return Size(Decimal.__mod__(self, other, context=context))
- def convertTo(self, spec="", xlate=False): + def convertTo(self, spec=None): """ Return the size in the units indicated by the specifier.
- :param str spec: a units specifier + :param spec: a units specifier :returns: a numeric value in the units indicated by the specifier :rtype: Decimal """ - unit = _parseUnits(spec, xlate) - if unit: - return Decimal(self) / Decimal(unit.factor) - - return None + return Decimal(self) / Decimal((spec or B).factor)
def humanReadable(self, max_places=2, strip=True, min_value=1, xlate=True): """ Return a string representation of this size with appropriate @@ -379,7 +375,7 @@ class Size(Decimal):
def roundToNearest(self, unit, rounding=ROUND_DEFAULT): """ - :param str unit: a unit specifier + :param unit: a unit specifier, a named constant like KiB :keyword rounding: which direction to round :type rounding: one of ROUND_UP, ROUND_DOWN, or ROUND_DEFAULT :returns: Size rounded to nearest whole specified unit @@ -389,4 +385,4 @@ class Size(Decimal): raise ValueError("invalid rounding specifier")
rounded = self.convertTo(unit).to_integral_value(rounding=rounding) - return Size("%s %s" % (rounded, unit)) + return Size(rounded * unit.factor) diff --git a/tests/size_test.py b/tests/size_test.py index 1ec7fbd..a3ee311 100644 --- a/tests/size_test.py +++ b/tests/size_test.py @@ -44,34 +44,32 @@ class SizeTestCase(unittest.TestCase):
self.assertEqual(s.humanReadable(max_places=0), "500 B")
- def _prefixTestHelper(self, numunits, factor, prefix, abbr): + def _prefixTestHelper(self, numunits, unit): """ Test that units and prefix or abbreviation agree.
:param int numunits: this value times factor yields number of bytes - :param int factor: this value times numunits yields number of bytes - :param str prefix: the prefix used to specify the units - :param str abbr: the abbreviation used to specify the units + :param unit: a unit specifier """ - c = numunits * factor + c = numunits * unit.factor
s = Size(c) self.assertEquals(s, Size(c))
- u = size._makeSpec(prefix, size._BYTES_WORDS[0], False) + u = size._makeSpec(unit.prefix, size._BYTES_WORDS[0], False) s = Size("%ld %s" % (numunits, u)) self.assertEquals(s, c) - self.assertEquals(s.convertTo(spec=u), numunits) + self.assertEquals(s.convertTo(unit), numunits)
- u = size._makeSpec(abbr, size._BYTES_SYMBOL, False) + u = size._makeSpec(unit.abbr, size._BYTES_SYMBOL, False) s = Size("%ld %s" % (numunits, u)) self.assertEquals(s, c) - self.assertEquals(s.convertTo(spec=u), numunits) + self.assertEquals(s.convertTo(unit), numunits)
def testPrefixes(self): numbytes = 47
- for factor, prefix, abbr in [_EMPTY_PREFIX] + _BINARY_PREFIXES + _DECIMAL_PREFIXES: - self._prefixTestHelper(numbytes, factor, prefix, abbr) + for unit in [_EMPTY_PREFIX] + _BINARY_PREFIXES + _DECIMAL_PREFIXES: + self._prefixTestHelper(numbytes, unit)
def testHumanReadable(self): s = Size(58929971) @@ -170,15 +168,15 @@ class SizeTestCase(unittest.TestCase):
def testConvertToPrecision(self): s = Size(1835008) - self.assertEquals(s.convertTo(spec=""), 1835008) - self.assertEquals(s.convertTo(spec="b"), 1835008) - self.assertEquals(s.convertTo(spec="KiB"), 1792) - self.assertEquals(s.convertTo(spec="MiB"), 1.75) + self.assertEquals(s.convertTo(None), 1835008) + self.assertEquals(s.convertTo(size.B), 1835008) + self.assertEquals(s.convertTo(size.KiB), 1792) + self.assertEquals(s.convertTo(size.MiB), 1.75)
def testNegative(self): s = Size("-500MiB") self.assertEquals(s.humanReadable(), "-500 MiB") - self.assertEquals(s.convertTo(spec="b"), -524288000) + self.assertEquals(s.convertTo(size.B), -524288000)
def testPartialBytes(self): self.assertEquals(Size(1024.6), Size(1024)) @@ -297,40 +295,40 @@ class TranslationTestCase(unittest.TestCase): self.assertEqual(size.ROUND_DEFAULT, size.ROUND_HALF_UP)
s = Size("10.3 GiB") - self.assertEqual(s.roundToNearest("GiB"), Size("10 GiB")) - self.assertEqual(s.roundToNearest("GiB", rounding=size.ROUND_DEFAULT), + self.assertEqual(s.roundToNearest(size.GiB), Size("10 GiB")) + self.assertEqual(s.roundToNearest(size.GiB, rounding=size.ROUND_DEFAULT), Size("10 GiB")) - self.assertEqual(s.roundToNearest("GiB", rounding=size.ROUND_DOWN), + self.assertEqual(s.roundToNearest(size.GiB, rounding=size.ROUND_DOWN), Size("10 GiB")) - self.assertEqual(s.roundToNearest("GiB", rounding=size.ROUND_UP), + self.assertEqual(s.roundToNearest(size.GiB, rounding=size.ROUND_UP), Size("11 GiB")) - # >>> Size("10.3 GiB").convertTo("MiB") + # >>> Size("10.3 GiB").convertTo(size.MiB) # Decimal('10547.19999980926513671875') - self.assertEqual(s.roundToNearest("MiB"), Size("10547 MiB")) - self.assertEqual(s.roundToNearest("MiB", rounding=size.ROUND_UP), + self.assertEqual(s.roundToNearest(size.MiB), Size("10547 MiB")) + self.assertEqual(s.roundToNearest(size.MiB, rounding=size.ROUND_UP), Size("10548 MiB")) - self.assertIsInstance(s.roundToNearest("MiB"), Size) + self.assertIsInstance(s.roundToNearest(size.MiB), Size) with self.assertRaises(ValueError): - s.roundToNearest("MiB", rounding='abc') + s.roundToNearest(size.MiB, rounding='abc')
# arbitrary decimal rounding constants are not allowed from decimal import ROUND_HALF_DOWN with self.assertRaises(ValueError): - s.roundToNearest("MiB", rounding=ROUND_HALF_DOWN) + s.roundToNearest(size.MiB, rounding=ROUND_HALF_DOWN)
s = Size("10.51 GiB") - self.assertEqual(s.roundToNearest("GiB"), Size("11 GiB")) - self.assertEqual(s.roundToNearest("GiB", rounding=size.ROUND_DEFAULT), + self.assertEqual(s.roundToNearest(size.GiB), Size("11 GiB")) + self.assertEqual(s.roundToNearest(size.GiB, rounding=size.ROUND_DEFAULT), Size("11 GiB")) - self.assertEqual(s.roundToNearest("GiB", rounding=size.ROUND_DOWN), + self.assertEqual(s.roundToNearest(size.GiB, rounding=size.ROUND_DOWN), Size("10 GiB")) - self.assertEqual(s.roundToNearest("GiB", rounding=size.ROUND_UP), + self.assertEqual(s.roundToNearest(size.GiB, rounding=size.ROUND_UP), Size("11 GiB"))
s = Size("513 GiB") - self.assertEqual(s.roundToNearest("GiB"), s) - self.assertEqual(s.roundToNearest("TiB"), Size("1 TiB")) - self.assertEqual(s.roundToNearest("TiB", rounding=size.ROUND_DOWN), + self.assertEqual(s.roundToNearest(size.GiB), s) + self.assertEqual(s.roundToNearest(size.TiB), Size("1 TiB")) + self.assertEqual(s.roundToNearest(size.TiB, rounding=size.ROUND_DOWN), Size(0))
class UtilityMethodsTestCase(unittest.TestCase): diff --git a/tests/storagetestcase.py b/tests/storagetestcase.py index 54d6c15..0b3f26d 100644 --- a/tests/storagetestcase.py +++ b/tests/storagetestcase.py @@ -12,6 +12,8 @@ from blivet.formats import getFormat from blivet.devices import StorageDevice from blivet.devices import PartitionDevice
+from blivet.size import B + class StorageTestCase(unittest.TestCase): """ StorageTestCase
@@ -94,7 +96,7 @@ class StorageTestCase(unittest.TestCase): if exists: # set up mock parted.Device w/ correct size device._partedDevice = Mock() - device._partedDevice.getLength = Mock(return_value=int(device._size.convertTo(spec="B"))) + device._partedDevice.getLength = Mock(return_value=int(device._size.convertTo(B))) device._partedDevice.sectorSize = 512
if isinstance(device, blivet.devices.PartitionDevice):
It's equivalent and the value that is desired.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/size.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/blivet/size.py b/blivet/size.py index 2275b22..1133508 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -352,7 +352,7 @@ class Size(Decimal): # requirement use the largest prefix. limit = _BINARY_FACTOR * min_value for unit in [_EMPTY_PREFIX] + _BINARY_PREFIXES: - newcheck = super(Size, self).__div__(Decimal(unit.factor)) + newcheck = self.convertTo(unit)
if abs(newcheck) < limit: break
The different resize utilities require different args and sometimes different units specifications as well.
Be explicit that it needs to be overridden.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/formats/fs.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index e09d1e5..10c83ca 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -431,8 +431,14 @@ class FS(DeviceFormat):
@property def resizeArgs(self): - argv = [self.device, "%d" % (self.targetSize.convertTo(MiB),)] - return argv + """ Returns the arguments for resizing the filesystem. + + Must be overridden by every class that has non-None _resizefs. + + :returns: arguments for resizing a filesystem. + :rtype: list of str + """ + return []
def doResize(self): """ Resize this filesystem based on this instance's targetSize attr.
The reason it is used elsewhere, i.e., when calculating minimum size is because of the constraint on the resizeArgs() method to use the units defined by _resizefsUnit. This patch makes that explicit.
This patch doesn't change behavior, it replaces a literal with an already defined constant of the same value in appropriate places.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/formats/fs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 10c83ca..6de4f6f 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1047,7 +1047,7 @@ class Ext2FS(FS):
@property def resizeArgs(self): - argv = ["-p", self.device, "%dM" % (self.targetSize.convertTo(MiB))] + argv = ["-p", self.device, "%dM" % (self.targetSize.convertTo(self._resizefsUnit))] return argv
register_device_format(Ext2FS) @@ -1446,7 +1446,7 @@ class NTFS(FS): def resizeArgs(self): # You must supply at least two '-f' options to ntfsresize or # the proceed question will be presented to you. - argv = ["-ff", "-s", "%d" % self.targetSize.convertTo(B), + argv = ["-ff", "-s", "%d" % self.targetSize.convertTo(self._resizefsUnit), self.device] return argv
On 12/23/2014 05:42 PM, mulhern wrote:
The reason it is used elsewhere, i.e., when calculating minimum size is because of the constraint on the resizeArgs() method to use the units defined by _resizefsUnit. This patch makes that explicit.
This patch doesn't change behavior, it replaces a literal with an already defined constant of the same value in appropriate places.
This patch has already been proposed and rejected. Why is it being proposed again unchanged?
Signed-off-by: mulhern amulhern@redhat.com
blivet/formats/fs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 10c83ca..6de4f6f 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1047,7 +1047,7 @@ class Ext2FS(FS):
@property def resizeArgs(self):
argv = ["-p", self.device, "%dM" % (self.targetSize.convertTo(MiB))]
argv = ["-p", self.device, "%dM" % (self.targetSize.convertTo(self._resizefsUnit))] return argvregister_device_format(Ext2FS)
@@ -1446,7 +1446,7 @@ class NTFS(FS): def resizeArgs(self): # You must supply at least two '-f' options to ntfsresize or # the proceed question will be presented to you.
argv = ["-ff", "-s", "%d" % self.targetSize.convertTo(B),
argv = ["-ff", "-s", "%d" % self.targetSize.convertTo(self._resizefsUnit), self.device] return argv
----- Original Message -----
From: "David Lehman" dlehman@redhat.com To: anaconda-patches@lists.fedorahosted.org Sent: Wednesday, January 7, 2015 12:16:36 PM Subject: Re: [blivet:master 17/20] Use _resizefsUnit in resizeArgs() method implementations.
On 12/23/2014 05:42 PM, mulhern wrote:
The reason it is used elsewhere, i.e., when calculating minimum size is because of the constraint on the resizeArgs() method to use the units defined by _resizefsUnit. This patch makes that explicit.
This patch doesn't change behavior, it replaces a literal with an already defined constant of the same value in appropriate places.
This patch has already been proposed and rejected. Why is it being proposed again unchanged?
This change was originally part of a larger patch. I didn't want the whole patch to be condemned on account of one part, so I separated that patch into its distinct changes.
I'll drop this patch.
- mulhern
Signed-off-by: mulhern amulhern@redhat.com
blivet/formats/fs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 10c83ca..6de4f6f 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1047,7 +1047,7 @@ class Ext2FS(FS):
@property def resizeArgs(self):
argv = ["-p", self.device, "%dM" %(self.targetSize.convertTo(MiB))]
argv = ["-p", self.device, "%dM" %(self.targetSize.convertTo(self._resizefsUnit))] return argv
register_device_format(Ext2FS) @@ -1446,7 +1446,7 @@ class NTFS(FS): def resizeArgs(self): # You must supply at least two '-f' options to ntfsresize or # the proceed question will be presented to you.
argv = ["-ff", "-s", "%d" % self.targetSize.convertTo(B),
argv = ["-ff", "-s", "%d" %self.targetSize.convertTo(self._resizefsUnit), self.device] return argv
anaconda-patches mailing list anaconda-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
Does not change behavior, just replaces a literal with an already defined constant.
TmpFS has no method for obtaining the minimum size, so in blivet's current state it is not resizable.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/formats/fs.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 6de4f6f..908364f 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1556,6 +1556,7 @@ class TmpFS(NoDevFS): # remounting can be used to change # the size of a live tmpfs mount _resizefs = "mount" + _resizefsUnit = MiB # as tmpfs is part of the Linux kernel, # it is Linux-native _linuxNative = True @@ -1593,7 +1594,7 @@ class TmpFS(NoDevFS): self._options = fsoptions if self._size: # absolute size for the tmpfs mount has been specified - self._size_option = "size=%dm" % self._size.convertTo(MiB) + self._size_option = "size=%dm" % self._size.convertTo(self._resizefsUnit) else: # if no size option is specified, the tmpfs mount size will be 50% # of system RAM by default @@ -1675,7 +1676,7 @@ class TmpFS(NoDevFS): # the mount command
# add the remount flag, size and any options - remount_options = 'remount,size=%dm' % self.targetSize.convertTo(MiB) + remount_options = 'remount,size=%dm' % self.targetSize.convertTo(self._resizefsUnit) # if any mount options are defined, append them if self._options: remount_options = "%s,%s" % (remount_options, self._options) @@ -1695,7 +1696,7 @@ class TmpFS(NoDevFS): # update the size option string # -> please note that resizing always sets the # size of this tmpfs mount to an absolute value - self._size_option = "size=%dm" % self._size.convertTo(MiB) + self._size_option = "size=%dm" % self._size.convertTo(self._resizefsUnit)
register_device_format(TmpFS)
This allows to specify Sizes with units reasonably succinctly, but at the same time to avoid the long and costly _parseSpec() path.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/size.py | 38 ++++++++++++++++++++++---------------- tests/size_test.py | 4 ++++ 2 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/blivet/size.py b/blivet/size.py index 1133508..de1d118 100644 --- a/blivet/size.py +++ b/blivet/size.py @@ -225,22 +225,24 @@ class Size(Decimal): """
def __new__(cls, value=0, context=None): - """ Initialize a new Size object. Must pass a bytes or a spec value - for size. The bytes value is a numerical value for the size - this object represents, in bytes. The spec value is a string - specification of the size using any of the size specifiers in the - _DECIMAL_PREFIXES or _BINARY_PREFIXES lists combined with a 'b' or - 'B'. For example, to specify 640 kilobytes, you could pass any of - these spec parameters: - - "640kb" - "640 kb" - "640KB" - "640 KB" - "640 kilobytes" - - If you want to use a spec value to represent a bytes value, - you can use the letter 'b' or 'B' or omit the size specifier. + """ Initialize a new Size object. + + :param value: specification of the number of bytes + :type value: tuple, str, Size, or any number type + + A tuple value must consists of a pair of a number and a unit + specifier like those as an argument to convertTo(). For example, + (640, size.KiB) represents 640 KiB. + + A str value combines the number and the units into a simple string + specification, like "640 KiB". The string specification is + the most appropriate for user input size specifications, as it + can handle locale-specific unit specifications and long word + specifications like "640 kilobytes". + + A Size value works like a copy constructor. + + A numeric value is taken to represent the number of bytes. """ if isinstance(value, (six.string_types, bytes)): size = _parseSpec(value) @@ -248,6 +250,10 @@ class Size(Decimal): size = Decimal(value) elif isinstance(value, Size): size = Decimal(value.convertTo()) + elif isinstance(value, tuple) and len(value) == 2 and \ + isinstance(value[0], (six.integer_types, float, Decimal)) and \ + isinstance(value[1], _Prefix): + size = Decimal(value[0] * value[1].factor) else: raise ValueError("invalid value %s for size" % value)
diff --git a/tests/size_test.py b/tests/size_test.py index a3ee311..b25678a 100644 --- a/tests/size_test.py +++ b/tests/size_test.py @@ -57,12 +57,16 @@ class SizeTestCase(unittest.TestCase):
u = size._makeSpec(unit.prefix, size._BYTES_WORDS[0], False) s = Size("%ld %s" % (numunits, u)) + t = Size((numunits, unit)) self.assertEquals(s, c) + self.assertEquals(t, c) self.assertEquals(s.convertTo(unit), numunits)
u = size._makeSpec(unit.abbr, size._BYTES_SYMBOL, False) s = Size("%ld %s" % (numunits, u)) + t = Size((numunits, unit)) self.assertEquals(s, c) + self.assertEquals(t, c) self.assertEquals(s.convertTo(unit), numunits)
def testPrefixes(self):
--- blivet/devicefactory.py | 6 +++--- blivet/devicelibs/btrfs.py | 4 ++-- blivet/devicelibs/crypto.py | 4 ++-- blivet/devicelibs/lvm.py | 18 +++++++++--------- blivet/devicelibs/mdraid.py | 10 +++++----- blivet/devicelibs/swap.py | 10 +++++----- blivet/devices/partition.py | 4 ++-- blivet/formats/biosboot.py | 6 +++--- blivet/formats/fs.py | 44 ++++++++++++++++++++++---------------------- blivet/formats/prepboot.py | 6 +++--- blivet/formats/swap.py | 4 ++-- blivet/partitioning.py | 6 +++--- blivet/platform.py | 22 +++++++++++----------- blivet/udev.py | 12 ++++++------ blivet/util.py | 6 +++--- 15 files changed, 81 insertions(+), 81 deletions(-)
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py index c383b4d..3fc5c6b 100644 --- a/blivet/devicefactory.py +++ b/blivet/devicefactory.py @@ -31,7 +31,7 @@ from .devicelibs import raid from .partitioning import SameSizeSet from .partitioning import TotalSizeSet from .partitioning import doPartitioning -from .size import Size +from .size import Size, MiB
import logging log = logging.getLogger("blivet") @@ -844,7 +844,7 @@ class PartitionFactory(DeviceFactory): if self.encrypted: min_format_size += getFormat("luks").minSize
- return max(Size("1MiB"), min_format_size) + return max(Size((1, MiB)), min_format_size)
def _get_device_size(self): """ Return the factory device size including container limitations. """ @@ -982,7 +982,7 @@ class PartitionSetFactory(PartitionFactory): add_disks = self.disks
# drop any new disks that don't have free space - min_free = min(Size("500MiB"), self.parent_factory.size) + min_free = min(Size((500, MiB)), self.parent_factory.size) add_disks = [d for d in add_disks if d.partitioned and d.format.free >= min_free]
diff --git a/blivet/devicelibs/btrfs.py b/blivet/devicelibs/btrfs.py index a0a4ec8..21fb75d 100644 --- a/blivet/devicelibs/btrfs.py +++ b/blivet/devicelibs/btrfs.py @@ -26,7 +26,7 @@ import re from . import raid from .. import util from ..errors import BTRFSError, BTRFSValueError -from ..size import Size +from ..size import Size, MiB
import logging log = logging.getLogger("blivet") @@ -35,7 +35,7 @@ log = logging.getLogger("blivet") MAIN_VOLUME_ID = 5
# if any component device is less than this size, mkfs.btrfs will fail -MIN_MEMBER_SIZE = Size("16 MiB") +MIN_MEMBER_SIZE = Size((16, MiB))
RAID_levels = raid.RAIDLevels(["raid0", "raid1", "raid10", "single"])
diff --git a/blivet/devicelibs/crypto.py b/blivet/devicelibs/crypto.py index 13a6282..a3588c8 100644 --- a/blivet/devicelibs/crypto.py +++ b/blivet/devicelibs/crypto.py @@ -25,10 +25,10 @@ import time from pycryptsetup import CryptSetup
from ..errors import CryptoError -from ..size import Size +from ..size import Size, MiB from ..util import get_current_entropy
-LUKS_METADATA_SIZE = Size("2 MiB") +LUKS_METADATA_SIZE = Size((2, MiB)) MIN_CREATE_ENTROPY = 256 # bits
# Keep the character set size a power of two to make sure all characters are diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py index ce576e2..91edee7 100644 --- a/blivet/devicelibs/lvm.py +++ b/blivet/devicelibs/lvm.py @@ -27,7 +27,7 @@ import logging log = logging.getLogger("blivet")
from . import raid -from ..size import Size, KiB, MiB +from ..size import Size, EiB, GiB, KiB, MiB, TiB from .. import util from .. import arch from ..errors import LVMError @@ -37,14 +37,14 @@ from ..flags import flags MAX_LV_SLOTS = 256
# some of lvm's defaults that we have no way to ask it for -LVM_PE_START = Size("1 MiB") -LVM_PE_SIZE = Size("4 MiB") +LVM_PE_START = Size((1, MiB)) +LVM_PE_SIZE = Size((4, MiB))
# thinp constants -LVM_THINP_MIN_METADATA_SIZE = Size("2 MiB") -LVM_THINP_MAX_METADATA_SIZE = Size("16 GiB") -LVM_THINP_MIN_CHUNK_SIZE = Size("64 KiB") -LVM_THINP_MAX_CHUNK_SIZE = Size("1 GiB") +LVM_THINP_MIN_METADATA_SIZE = Size((2, MiB)) +LVM_THINP_MAX_METADATA_SIZE = Size((16, GiB)) +LVM_THINP_MIN_CHUNK_SIZE = Size((64, KiB)) +LVM_THINP_MAX_CHUNK_SIZE = Size((1, GiB))
RAID_levels = raid.RAIDLevels(["raid0", "raid1", "linear"])
@@ -134,9 +134,9 @@ def getPossiblePhysicalExtents(): def getMaxLVSize(): """ Return the maximum size of a logical volume. """ if arch.getArch() in ("x86_64", "ppc64", "ppc64le", "alpha", "ia64", "s390"): #64bit architectures - return Size("8 EiB") + return Size((8, EiB)) else: - return Size("16 TiB") + return Size((16, TiB))
def clampSize(size, pesize, roundup=None): delta = size % pesize diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py index 5479a03..d159dde 100644 --- a/blivet/devicelibs/mdraid.py +++ b/blivet/devicelibs/mdraid.py @@ -26,15 +26,15 @@ import string
from .. import util from ..errors import MDRaidError -from ..size import Size +from ..size import Size, KiB, MiB from . import raid
import logging log = logging.getLogger("blivet")
# these defaults were determined empirically -MD_SUPERBLOCK_SIZE = Size("2 MiB") -MD_CHUNK_SIZE = Size("512 KiB") +MD_SUPERBLOCK_SIZE = Size((2, MiB)) +MD_CHUNK_SIZE = Size((512, KiB))
class MDRaidLevels(raid.RAIDLevels): @classmethod @@ -70,8 +70,8 @@ def get_raid_superblock_size(size, version=None): # MDADM: operations, but limit this to 128Meg (0.1% of 10Gig) # MDADM: which is plenty for efficient reshapes # NOTE: In the mdadm code this is in 512b sectors. Converted to use MiB - MIN_HEADROOM = Size("1 MiB") - headroom = int(Size("128 MiB")) + MIN_HEADROOM = Size((1, MiB)) + headroom = int(Size((128, MiB))) while Size(headroom << 10) > size and Size(headroom) > MIN_HEADROOM: headroom >>= 1
diff --git a/blivet/devicelibs/swap.py b/blivet/devicelibs/swap.py index 28c8d2a..e6d6a6b 100644 --- a/blivet/devicelibs/swap.py +++ b/blivet/devicelibs/swap.py @@ -27,7 +27,7 @@ from decimal import Decimal from ..errors import DMError, OldSwapError, SuspendError, SwapError, UnknownSwapError from .. import util from . import dm -from ..size import Size +from ..size import Size, GiB
import logging log = logging.getLogger("blivet") @@ -137,20 +137,20 @@ def swapSuggestion(quiet=False, hibernation=False, disk_space=None): if not quiet: log.info("Detected %s of memory", mem)
- sixtyfour_GiB = Size("64 GiB") + sixtyfour_GiB = Size((64, GiB))
#chart suggested in the discussion with other teams - if mem < Size("2 GiB"): + if mem < Size((2, GiB)): swap = 2 * mem
- elif mem < Size("8 GiB"): + elif mem < Size((8, GiB)): swap = mem
elif mem < sixtyfour_GiB: swap = mem / 2
else: - swap = Size("4 GiB") + swap = Size((4, GiB))
if hibernation: if mem <= sixtyfour_GiB: diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py index be42de5..699210d 100644 --- a/blivet/devices/partition.py +++ b/blivet/devices/partition.py @@ -54,7 +54,7 @@ class PartitionDevice(StorageDevice): """ _type = "partition" _resizable = True - defaultSize = Size("500MiB") + defaultSize = Size((500, MiB))
def __init__(self, name, fmt=None, size=None, grow=False, maxsize=None, start=None, end=None, @@ -537,7 +537,7 @@ class PartitionDevice(StorageDevice): device = self.partedPartition.geometry.device.path
# Erase 1MiB or to end of partition - count = min(int(Size("1 MiB") // bs), part_len) + count = min(int(Size((1, MiB)) // bs), part_len)
cmd = ["dd", "if=/dev/zero", "of=%s" % device, "bs=%s" % bs, "seek=%s" % start, "count=%s" % count] diff --git a/blivet/formats/biosboot.py b/blivet/formats/biosboot.py index 0c6c251..c635bec 100644 --- a/blivet/formats/biosboot.py +++ b/blivet/formats/biosboot.py @@ -22,7 +22,7 @@
from parted import PARTITION_BIOS_GRUB
-from ..size import Size +from ..size import Size, KiB, MiB from .. import platform from ..i18n import N_ from . import DeviceFormat, register_device_format @@ -34,8 +34,8 @@ class BIOSBoot(DeviceFormat): partedFlag = PARTITION_BIOS_GRUB _formattable = True # can be formatted _linuxNative = True # for clearpart - _maxSize = Size("2 MiB") - _minSize = Size("512 KiB") + _maxSize = Size((2, MiB)) + _minSize = Size((512, KiB))
def __init__(self, **kwargs): """ diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 908364f..5a8a4a6 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -35,7 +35,7 @@ from ..flags import flags from parted import fileSystemType from ..storage_log import log_exception_info, log_method_call from .. import arch -from ..size import Size, ROUND_UP, ROUND_DOWN, MiB, B, unitStr +from ..size import Size, ROUND_UP, ROUND_DOWN, EiB, KiB, MiB, MB, TiB, B, unitStr from ..i18n import _, N_ from .. import udev
@@ -941,7 +941,7 @@ class Ext2FS(FS): _supported = True _resizable = True _linuxNative = True - _maxSize = Size("8 TiB") + _maxSize = Size((8, TiB)) _defaultCheckOptions = ["-f", "-p", "-C", "0"] _dump = True _check = True @@ -1024,7 +1024,7 @@ class Ext2FS(FS): log.debug("size=%s, current=%s", size, self.currentSize) # add some padding size = min(size * Decimal('1.1'), - size + Size("500 MiB")) + size + Size((500, MiB))) # make sure that the padded and rounded min size is not larger # than the current size size = min(size.roundToNearest(self._resizefsUnit, @@ -1064,7 +1064,7 @@ class Ext3FS(Ext2FS): # smaller than the default of 4096 bytes and therefore to make liars of us # with regard to this maximum filesystem size, but if they're doing such # things they should know the implications of their chosen block size. - _maxSize = Size("16 TiB") + _maxSize = Size((16, TiB))
@property def needsFSCheck(self): @@ -1095,7 +1095,7 @@ class FATFS(FS): 2: N_("Usage error.")} _supported = True _formattable = True - _maxSize = Size("1 TiB") + _maxSize = Size((1, TiB)) _packages = [ "dosfstools" ] _defaultMountOptions = ["umask=0077", "shortname=winnt"] _defaultCheckOptions = ["-n"] @@ -1117,7 +1117,7 @@ class EFIFS(FATFS): _type = "efi" _mountType = "vfat" _name = N_("EFI System Partition") - _minSize = Size("50 MiB") + _minSize = Size((50, MiB))
@property def supported(self): @@ -1136,8 +1136,8 @@ class BTRFS(FS): _linuxNative = True _supported = True _packages = ["btrfs-progs"] - _minSize = Size("256 MiB") - _maxSize = Size("16 EiB") + _minSize = Size((256, MiB)) + _maxSize = Size((16, EiB)) # FIXME parted needs to be taught about btrfs so that we can set the # partition table type correctly for btrfs partitions # partedSystem = fileSystemType["btrfs"] @@ -1218,7 +1218,7 @@ class JFS(FS): _modules = ["jfs"] _labelfs = fslabeling.JFSLabeling() _defaultFormatOptions = ["-q"] - _maxSize = Size("8 TiB") + _maxSize = Size((8, TiB)) _formattable = True _linuxNative = True _dump = True @@ -1247,7 +1247,7 @@ class ReiserFS(FS): _labelfs = fslabeling.ReiserFSLabeling() _modules = ["reiserfs"] _defaultFormatOptions = ["-f", "-f"] - _maxSize = Size("16 TiB") + _maxSize = Size((16, TiB)) _formattable = True _linuxNative = True _dump = True @@ -1276,7 +1276,7 @@ class XFS(FS): _modules = ["xfs"] _labelfs = fslabeling.XFSLabeling() _defaultFormatOptions = ["-f"] - _maxSize = Size("16 EiB") + _maxSize = Size((16, EiB)) _formattable = True _linuxNative = True _supported = True @@ -1324,8 +1324,8 @@ class AppleBootstrapFS(HFS): _type = "appleboot" _mountType = "hfs" _name = N_("Apple Bootstrap") - _minSize = Size("768 KiB") - _maxSize = Size("1 MiB") + _minSize = Size((768, KiB)) + _maxSize = Size((1, MiB))
@property def supported(self): @@ -1345,8 +1345,8 @@ class HFSPlus(FS): _labelfs = fslabeling.HFSPlusLabeling() _formattable = True _mountType = "hfsplus" - _minSize = Size("1 MiB") - _maxSize = Size("2 TiB") + _minSize = Size((1, MiB)) + _maxSize = Size((2, TiB)) _check = True partedSystem = fileSystemType["hfs+"]
@@ -1358,7 +1358,7 @@ class MacEFIFS(HFSPlus): _name = N_("Linux HFS+ ESP") _labelfs = fslabeling.HFSPlusLabeling() _udevTypes = [] - _minSize = Size("50 MiB") + _minSize = Size((50, MiB))
@property def supported(self): @@ -1381,8 +1381,8 @@ class NTFS(FS): _labelfs = fslabeling.NTFSLabeling() _fsck = "ntfsresize" _resizable = True - _minSize = Size("1 MiB") - _maxSize = Size("16 TiB") + _minSize = Size((1, MiB)) + _maxSize = Size((16, TiB)) _defaultMountOptions = ["defaults", "ro"] _defaultCheckOptions = ["-c"] _packages = ["ntfsprogs"] @@ -1414,7 +1414,7 @@ class NTFS(FS): continue try: # ntfsresize uses SI unit prefixes - minSize = Size("%d mb" % int(l.split(":")[1].strip())) + minSize = Size((int(l.split(":")[1].strip()), MB)) except (IndexError, ValueError) as e: minSize = None log.warning("Unable to parse output for minimum size on %s: %s", self.device, e) @@ -1425,7 +1425,7 @@ class NTFS(FS): else: # add some padding to the min size size = min(minSize * Decimal('1.1'), - minSize + Size("500 MiB")) + minSize + Size((500, MiB))) # make sure the padded and rounded min size is not larger than # the current size size = min(size.roundToNearest(self._resizefsUnit, @@ -1576,9 +1576,9 @@ class TmpFS(NoDevFS): # and 16EB on 64 bit systems bits = arch.numBits() if bits == 32: - self._maxSize = Size("16TiB") + self._maxSize = Size((16, TiB)) elif bits == 64: - self._maxSize = Size("16EiB") + self._maxSize = Size((16, EiB)) # if the architecture is other than 32 or 64 bit or unknown # just use the default maxsize, which is 0, this disables # resizing but other operations such as mounting should work fine diff --git a/blivet/formats/prepboot.py b/blivet/formats/prepboot.py index e44967a..3b5c29f 100644 --- a/blivet/formats/prepboot.py +++ b/blivet/formats/prepboot.py @@ -21,7 +21,7 @@ #
from ..errors import FormatCreateError -from ..size import Size +from ..size import Size, MiB from .. import platform from ..i18n import N_ from . import DeviceFormat, register_device_format @@ -37,8 +37,8 @@ class PPCPRePBoot(DeviceFormat): partedFlag = PARTITION_PREP _formattable = True # can be formatted _linuxNative = True # for clearpart - _maxSize = Size("10 MiB") - _minSize = Size("4 MiB") + _maxSize = Size((10, MiB)) + _minSize = Size((4, MiB))
def __init__(self, **kwargs): """ diff --git a/blivet/formats/swap.py b/blivet/formats/swap.py index ce85a6a..1bc4a81 100644 --- a/blivet/formats/swap.py +++ b/blivet/formats/swap.py @@ -25,7 +25,7 @@ from ..storage_log import log_method_call from ..errors import SwapSpaceError from ..devicelibs import swap from . import DeviceFormat, register_device_format -from ..size import Size +from ..size import Size, GiB
import logging log = logging.getLogger("blivet") @@ -43,7 +43,7 @@ class SwapSpace(DeviceFormat): _linuxNative = True # for clearpart
#see rhbz#744129 for details - _maxSize = Size("128 GiB") + _maxSize = Size((128, GiB))
def __init__(self, **kwargs): """ diff --git a/blivet/partitioning.py b/blivet/partitioning.py index ef4d328..5b05389 100644 --- a/blivet/partitioning.py +++ b/blivet/partitioning.py @@ -31,7 +31,7 @@ from .flags import flags from .devices import PartitionDevice, LUKSDevice, devicePathToName from .formats import getFormat from .devicelibs.lvm import get_pool_padding -from .size import Size +from .size import Size, TiB from .i18n import _ from .util import stringize, unicodeize
@@ -611,7 +611,7 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None, continue
if boot: - max_boot = Size("2 TiB") + max_boot = Size((2, TiB)) free_start = Size(free_geom.start * disk.device.sectorSize) req_end = free_start + req_size if req_end > max_boot: @@ -1666,7 +1666,7 @@ class DiskChunk(Chunk):
# 2TB limit on bootable partitions, regardless of disklabel if req.device.req_bootable: - max_boot = sizeToSectors(Size("2 TiB"), self.sectorSize) + max_boot = sizeToSectors(Size((2, TiB)), self.sectorSize) limits.append(max_boot - req_end)
# request-specific maximum (see Request.__init__, above, for details) diff --git a/blivet/platform.py b/blivet/platform.py index dc349b2..6e30c74 100644 --- a/blivet/platform.py +++ b/blivet/platform.py @@ -28,7 +28,7 @@ from . import arch from . import devicelibs from .flags import flags from .partspec import PartSpec -from .size import Size +from .size import Size, GiB, MiB from .i18n import _, N_
class Platform(object): @@ -154,7 +154,7 @@ class Platform(object):
def setDefaultPartitioning(self): """Return the default platform-specific partitioning information.""" - return [PartSpec(mountpoint="/boot", size=Size("500MiB"), + return [PartSpec(mountpoint="/boot", size=Size((500, MiB)), weight=self.weight(mountpoint="/boot"))]
def weight(self, fstype=None, mountpoint=None): @@ -193,7 +193,7 @@ class X86(Platform): def setDefaultPartitioning(self): """Return the default platform-specific partitioning information.""" ret = Platform.setDefaultPartitioning(self) - ret.append(PartSpec(fstype="biosboot", size=Size("1MiB"), + ret.append(PartSpec(fstype="biosboot", size=Size((1, MiB)), weight=self.weight(fstype="biosboot"))) return ret
@@ -227,7 +227,7 @@ class EFI(Platform): def setDefaultPartitioning(self): ret = Platform.setDefaultPartitioning(self) ret.append(PartSpec(mountpoint="/boot/efi", fstype="efi", - size=Size("20MiB"), maxSize=Size("200MiB"), + size=Size((20, MiB)), maxSize=Size((200, MiB)), grow=True, weight=self.weight(fstype="efi"))) return ret
@@ -249,7 +249,7 @@ class MacEFI(EFI): def setDefaultPartitioning(self): ret = Platform.setDefaultPartitioning(self) ret.append(PartSpec(mountpoint="/boot/efi", fstype="macefi", - size=Size("20MiB"), maxSize=Size("200MiB"), + size=Size((20, MiB)), maxSize=Size((200, MiB)), grow=True, weight=self.weight(mountpoint="/boot/efi"))) return ret
@@ -266,7 +266,7 @@ class PPC(Platform):
class IPSeriesPPC(PPC): _boot_stage1_format_types = ["prepboot"] - _boot_stage1_max_end = Size("4 GiB") + _boot_stage1_max_end = Size((4, GiB)) _boot_prep_description = N_("PReP Boot Partition") _boot_descriptions = {"partition": _boot_prep_description} _disklabel_types = ["msdos", "gpt"] @@ -276,7 +276,7 @@ class IPSeriesPPC(PPC):
def setDefaultPartitioning(self): ret = PPC.setDefaultPartitioning(self) - ret.append(PartSpec(fstype="prepboot", size=Size("4MiB"), + ret.append(PartSpec(fstype="prepboot", size=Size((4, MiB)), weight=self.weight(fstype="prepboot"))) return ret
@@ -301,7 +301,7 @@ class NewWorldPPC(PPC):
def setDefaultPartitioning(self): ret = Platform.setDefaultPartitioning(self) - ret.append(PartSpec(fstype="appleboot", size=Size("1MiB"), + ret.append(PartSpec(fstype="appleboot", size=Size((1, MiB)), weight=self.weight(fstype="appleboot"))) return ret
@@ -336,7 +336,7 @@ class S390(Platform):
def setDefaultPartitioning(self): """Return the default platform-specific partitioning information.""" - return [PartSpec(mountpoint="/boot", size=Size("500MiB"), + return [PartSpec(mountpoint="/boot", size=Size((500, MiB)), weight=self.weight(mountpoint="/boot"), lv=False)] def requiredDiskLabelType(self, device_type): """The required disklabel type for the specified device type.""" @@ -383,11 +383,11 @@ class omapARM(ARM): def setDefaultPartitioning(self): """Return the ARM-OMAP platform-specific partitioning information.""" ret = [PartSpec(mountpoint="/boot/uboot", fstype="vfat", - size=Size("20MiB"), maxSize=Size("200MiB"), + size=Size((20, MiB)), maxSize=Size((200, MiB)), grow=True, weight=self.weight(fstype="vfat", mountpoint="/boot/uboot"))] ret.append(PartSpec(mountpoint="/", fstype="ext4", - size=Size("2GiB"), maxSize=Size("3GiB"), + size=Size((2, GiB)), maxSize=Size((3, GiB)), weight=self.weight(mountpoint="/"))) return ret
diff --git a/blivet/udev.py b/blivet/udev.py index 1ca9890..b8bb9d7 100644 --- a/blivet/udev.py +++ b/blivet/udev.py @@ -25,7 +25,7 @@ import os import re
from . import util -from .size import Size +from .size import Size, KiB from .flags import flags
import pyudev @@ -419,15 +419,15 @@ def device_get_vg_uuid(info): def device_get_vg_size(info): # lvm's decmial precision is not configurable, so we tell it to use # KB. - return Size("%s KiB" % info['LVM2_VG_SIZE']) + return Size((float(info['LVM2_VG_SIZE']), KiB))
def device_get_vg_free(info): # lvm's decmial precision is not configurable, so we tell it to use # KB. - return Size("%s KiB" % info['LVM2_VG_FREE']) + return Size((float(info['LVM2_VG_FREE']), KiB))
def device_get_vg_extent_size(info): - return Size("%s KiB" % info['LVM2_VG_EXTENT_SIZE']) + return Size((float(info['LVM2_VG_EXTENT_SIZE']), KiB))
def device_get_vg_extent_count(info): return int(info['LVM2_VG_EXTENT_COUNT']) @@ -439,7 +439,7 @@ def device_get_vg_pv_count(info): return int(info['LVM2_PV_COUNT'])
def device_get_pv_pe_start(info): - return Size("%s KiB" % info['LVM2_PE_START']) + return Size((float(info['LVM2_PE_START']), KiB))
def device_get_lv_name(info): return info['LVM2_LV_NAME'] @@ -448,7 +448,7 @@ def device_get_lv_uuid(info): return info['LVM2_LV_UUID']
def device_get_lv_size(info): - return Size("%s KiB" % info['LVM2_LV_SIZE']) + return Size((float(info['LVM2_LV_SIZE']), KiB))
def device_get_lv_attr(info): return info['LVM2_LV_ATTR'] diff --git a/blivet/util.py b/blivet/util.py index e3670a9..f941e6d 100644 --- a/blivet/util.py +++ b/blivet/util.py @@ -143,17 +143,17 @@ def total_memory(): :rtype: :class:`~.size.Size` """ # import locally to avoid a cycle with size importing util - from .size import Size + from .size import Size, KiB, MiB
lines = open("/proc/meminfo").readlines() for line in lines: if line.startswith("MemTotal:"): - mem = Size("%s KiB" % line.split()[1]) + mem = Size((float(line.split()[1]), KiB))
# Because /proc/meminfo only gives us the MemTotal (total physical RAM # minus the kernel binary code), we need to round this up. Assuming # every machine has the total RAM MiB number divisible by 128. */ - bs = Size("128MiB") + bs = Size((128, MiB)) mem = (mem / bs + 1) * bs return mem
I must say I don't like this change too much. Maybe we should make _parseSpec() faster for these "simple" cases? E.g. something like using s.endswith("KiB"), "MiB", "GiB",... or simple regexes first to check if it is a simple case we can just recognize right away?
----- Original Message -----
From: "Vratislav Podzimek" vpodzime@redhat.com To: "anaconda patch review" anaconda-patches@lists.fedorahosted.org Sent: Monday, January 5, 2015 3:08:34 AM Subject: Re: [blivet:master 20/20] Use tuples to construct Sizes() wherever units are known.
I must say I don't like this change too much. Maybe we should make _parseSpec() faster for these "simple" cases? E.g. something like using s.endswith("KiB"), "MiB", "GiB",... or simple regexes first to check if it is a simple case we can just recognize right away?
-- Vratislav Podzimek
Anaconda Rider | Red Hat, Inc. | Brno - Czech Republic
anaconda-patches mailing list anaconda-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
I'm withdrawing this patch and the preceding one.
The ultimate goal of this patch is to make use of named constants for Size() operations, rather than strings. Strings are cumbersome, expensive, and impossible for pylint to say anything useful about when they are used to represent units.
I strongly suspect that in the majority of cases, the units that are required for a Size are known at compile time, and that there is only a small set of cases where the units are derived from user input. For those cases, it would be more sensible to parse the user input using, e.g., _parseSpec(), passing the result to the Size constructor. In fact, it would really be better if anaconda handled the parsing according to its beliefs, and then simply constructed the Size() object that the user apparently wanted. blivet should not really be in the business of parsing user input.
This patch was a partial step toward that goal because I was trying to make it less invasive, but I think a more invasive patch set would be actually better in the long run.
- mulhern
anaconda-patches@lists.fedorahosted.org