[PATCH 6/6] Convert everything to use Size.

David Lehman dlehman at redhat.com
Tue Jan 7 23:51:01 UTC 2014


Size essentially stores sizes in bytes and provides methods for
conversion between various units.

All sizes originating from within blivet are based on binary prefixes
except where required to interface with other tools (see ntfsresize).

This adds a missing lower bound of 1 MiB to the md raid superblock size
calculation, which changes some of the mdraid tests.

It also reverses the order of the operands in the various
RAIDLevel._get_raw_array_size methods to ensure we return a Size instead
of an int.
---
 blivet/__init__.py                   |  28 +++--
 blivet/deviceaction.py               |   9 +-
 blivet/devicefactory.py              |  42 +++----
 blivet/devicelibs/crypto.py          |   3 +-
 blivet/devicelibs/lvm.py             |  85 ++++++++------
 blivet/devicelibs/mdraid.py          |  25 ++--
 blivet/devicelibs/raid.py            |  31 ++---
 blivet/devicelibs/swap.py            |  33 +++---
 blivet/devices.py                    | 214 +++++++++++++++++------------------
 blivet/devicetree.py                 |   9 +-
 blivet/formats/__init__.py           |   9 +-
 blivet/formats/biosboot.py           |   5 +-
 blivet/formats/disklabel.py          |   9 +-
 blivet/formats/dmraid.py             |   2 -
 blivet/formats/fs.py                 |  96 +++++++---------
 blivet/formats/lvmpv.py              |   4 +-
 blivet/formats/multipath.py          |   2 -
 blivet/formats/prepboot.py           |   5 +-
 blivet/formats/swap.py               |   3 +-
 blivet/partitioning.py               | 168 +++++++++++++--------------
 blivet/partspec.py                   |   2 +-
 blivet/platform.py                   |  32 +++---
 blivet/size.py                       |   8 +-
 blivet/udev.py                       |  21 ++--
 blivet/util.py                       |  21 ++--
 doc/intro.rst                        |  12 +-
 examples/factory.py                  |  13 ++-
 examples/lvm.py                      |  18 +--
 examples/partitioning.py             |  22 ++--
 tests/devicefactory_test.py          |   5 +-
 tests/devicelibs_test/lvm_test.py    |  15 ++-
 tests/devicelibs_test/mdraid_test.py |  32 ++++--
 tests/devices_test.py                | 115 +++++++++----------
 tests/size_test.py                   |   4 +-
 tests/storagetestcase.py             |   2 +
 35 files changed, 578 insertions(+), 526 deletions(-)

diff --git a/blivet/__init__.py b/blivet/__init__.py
index 1e6ac82..a70b32b 100644
--- a/blivet/__init__.py
+++ b/blivet/__init__.py
@@ -883,7 +883,6 @@ class Blivet(object):
                 The free space values are :class:`~.size.Size` instances.
 
         """
-        from size import Size
         if disks is None:
             disks = self.disks
 
@@ -895,11 +894,11 @@ class Blivet(object):
             should_clear = self.shouldClear(disk, clearPartType=clearPartType,
                                             clearPartDisks=[disk.name])
             if should_clear:
-                free[disk.name] = (Size(en_spec="%f mb" % disk.size), 0)
+                free[disk.name] = (disk.size, Size(bytes=0))
                 continue
 
-            disk_free = 0
-            fs_free = 0
+            disk_free = Size(bytes=0)
+            fs_free = Size(bytes=0)
             if disk.partitioned:
                 disk_free = disk.format.free
                 for partition in [p for p in self.partitions if p.disk == disk]:
@@ -918,8 +917,7 @@ class Blivet(object):
             elif disk.format.type is None:
                 disk_free = disk.size
 
-            free[disk.name] = (Size(en_spec="%f mb" % disk_free),
-                               Size(en_spec="%f mb" % fs_free))
+            free[disk.name] = (disk_free, fs_free)
 
         return free
 
@@ -1565,12 +1563,12 @@ class Blivet(object):
             problem = filesystems[mount].checkSize()
             if problem < 0:
                 errors.append(_("Your %(mount)s partition is too small for %(format)s formatting "
-                                "(allowable size is %(minSize)d MB to %(maxSize)d MB)")
+                                "(allowable size is %(minSize)s to %(maxSize)s)")
                               % {"mount": mount, "format": device.format.name,
                                  "minSize": device.minSize, "maxSize": device.maxSize})
             elif problem > 0:
                 errors.append(_("Your %(mount)s partition is too large for %(format)s formatting "
-                                "(allowable size is %(minSize)d MB to %(maxSize)d MB)")
+                                "(allowable size is %(minSize)s to %(maxSize)s)")
                               % {"mount":mount, "format": device.format.name,
                                  "minSize": device.minSize, "maxSize": device.maxSize})
 
@@ -1640,19 +1638,19 @@ class Blivet(object):
                 if missing:
                     errors.append(_("Your BIOS-based system needs a special "
                                     "partition to boot from a GPT disk label. "
-                                    "To continue, please create a 1MB "
+                                    "To continue, please create a 1MiB "
                                     "'biosboot' type partition."))
 
         if not swaps:
-            installed = Size(en_spec="%s kb" % util.total_memory())
-            required = Size(en_spec="%s kb" % isys.EARLY_SWAP_RAM)
+            installed = util.total_memory()
+            required = Size(en_spec="%s KiB" % isys.EARLY_SWAP_RAM)
 
             if installed < required:
                 errors.append(_("You have not specified a swap partition.  "
-                                "%(requiredMem)s MB of memory is required to continue installation "
-                                "without a swap partition, but you only have %(installedMem)s MB.")
-                              % {"requiredMem": int(required.convertTo(en_spec="MB")),
-                                 "installedMem": int(installed.convertTo(en_spec="MB"))})
+                                "%(requiredMem)s of memory is required to continue installation "
+                                "without a swap partition, but you only have %(installedMem)s.")
+                              % {"requiredMem": required,
+                                 "installedMem": installed})
             else:
                 warnings.append(_("You have not specified a swap partition.  "
                                   "Although not strictly required in all cases, "
diff --git a/blivet/deviceaction.py b/blivet/deviceaction.py
index b48462e..fc7257b 100644
--- a/blivet/deviceaction.py
+++ b/blivet/deviceaction.py
@@ -22,7 +22,6 @@
 #
 
 from udev import *
-import math
 
 from devices import StorageDevice
 from devices import PartitionDevice
@@ -383,7 +382,7 @@ class ActionResizeDevice(DeviceAction):
         if not device.resizable:
             raise ValueError("device is not resizable")
 
-        if long(math.floor(device.currentSize)) == newsize:
+        if device.currentSize == newsize:
             raise ValueError("new size same as old size")
 
         if newsize < device.minSize:
@@ -393,7 +392,7 @@ class ActionResizeDevice(DeviceAction):
             raise ValueError("new size is too large")
 
         DeviceAction.__init__(self, device)
-        if newsize > long(math.floor(device.currentSize)):
+        if newsize > device.currentSize:
             self.dir = RESIZE_GROW
         else:
             self.dir = RESIZE_SHRINK
@@ -590,11 +589,11 @@ class ActionResizeFormat(DeviceAction):
         if not device.format.resizable:
             raise ValueError("format is not resizable")
 
-        if long(math.floor(device.format.currentSize)) == newsize:
+        if device.format.currentSize == newsize:
             raise ValueError("new size same as old size")
 
         DeviceAction.__init__(self, device)
-        if newsize > long(math.floor(device.format.currentSize)):
+        if newsize > device.format.currentSize:
             self.dir = RESIZE_GROW
         else:
             self.dir = RESIZE_SHRINK
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py
index dbeb975..3a46605 100644
--- a/blivet/devicefactory.py
+++ b/blivet/devicefactory.py
@@ -31,6 +31,7 @@ from devicelibs.lvm import LVM_PE_SIZE
 from .partitioning import SameSizeSet
 from .partitioning import TotalSizeSet
 from .partitioning import doPartitioning
+from .size import Size
 
 import logging
 log = logging.getLogger("blivet")
@@ -155,7 +156,7 @@ class DeviceFactory(object):
             # PVs on each of the specified disks. No free space is maintained in
             # new VGs by default.
             factory = blivet.devicefactory.LVMFactory(_blivet,
-                                                      10000,
+                                                      Size(spec="10000 MB"),
                                                       disks,
                                                       fstype="xfs",
                                                       label="music",
@@ -168,7 +169,7 @@ class DeviceFactory(object):
             # Now add another LV to the "data" VG, adjusting the size of a non-
             # existent "data" VG so that it can contain the new LV.
             factory = blivet.devicefactory.LVMFactory(_blivet,
-                                                      20000,
+                                                      Size(spec="20000 MB"),
                                                       disks,
                                                       fstype="xfs",
                                                       label="videos",
@@ -179,7 +180,7 @@ class DeviceFactory(object):
             # Now change the size of the "music" LV and adjust the size of the
             # "data" VG accordingly.
             factory = blivet.devicefactory.LVMFactory(_blivet,
-                                                      15000,
+                                                      Size(spec="15000 MB"),
                                                       disks,
                                                       device=music_lv)
             factory.configure()
@@ -287,8 +288,7 @@ class DeviceFactory(object):
     #
     def _get_free_disk_space(self):
         free_info = self.storage.getFreeSpace(disks=self.disks)
-        free = sum(d[0] for d in free_info.values())
-        return int(free.convertTo(en_spec="mb"))
+        return sum(d[0] for d in free_info.values())
 
     def _handle_no_size(self):
         """ Set device size so that it grows to the largest size possible. """
@@ -795,7 +795,7 @@ class PartitionFactory(DeviceFactory):
             self.__fmt = getattr(self, "__fmt", getFormat(self.fstype))
             min_format_size = self.__fmt.minSize
 
-        return max(1, min_format_size)
+        return max(Size(en_spec="1MiB"), min_format_size)
 
     def _get_device_size(self):
         """ Return the factory device size including container limitations. """
@@ -804,7 +804,7 @@ class PartitionFactory(DeviceFactory):
     def _set_device_size(self):
         """ Set the size of a defined factory device. """
         if self.device and self.size != self.raw_device.size:
-            log.info("adjusting device size from %.2f to %.2f"
+            log.info("adjusting device size from %s to %s"
                             % (self.raw_device.size, self.size))
 
             base_size = self._get_base_size()
@@ -933,7 +933,7 @@ class PartitionSetFactory(PartitionFactory):
             add_disks = self.disks
 
         # drop any new disks that don't have free space
-        min_free = min(500, self.parent_factory.size)
+        min_free = min(Size(en_spec="500MiB"), self.parent_factory.size)
         add_disks = [d for d in add_disks if d.partitioned and
                                              d.format.free >= min_free]
 
@@ -1043,7 +1043,7 @@ class PartitionSetFactory(PartitionFactory):
         ##
         ## Set up SizeSet to manage growth of member partitions.
         ##
-        log.debug("adding a %s with size %d"
+        log.debug("adding a %s with size %s"
                   % (self.parent_factory.size_set_class.__name__, total_space))
         size_set = self.parent_factory.size_set_class(members, total_space)
         self.storage.size_sets.append(size_set)
@@ -1099,7 +1099,7 @@ class LVMFactory(DeviceFactory):
             free += self.raw_device.size
 
         if free < size:
-            log.info("adjusting size from %.2f to %.2f so it fits "
+            log.info("adjusting size from %s to %s so it fits "
                      "in container %s" % (size, free, self.container.name))
             size = free
 
@@ -1108,14 +1108,14 @@ class LVMFactory(DeviceFactory):
     def _set_device_size(self):
         size = self._get_device_size()
         if self.device and size != self.raw_device.size:
-            log.info("adjusting device size from %.2f to %.2f"
+            log.info("adjusting device size from %s to %s"
                             % (self.raw_device.size, size))
             self.raw_device.size = size
             self.raw_device.req_grow = False
 
     def _get_total_space(self):
         """ Total disk space requirement for this device and its container. """
-        size = 0
+        size = Size(bytes=0)
         if self.container and self.container.exists:
             return size
 
@@ -1128,10 +1128,10 @@ class LVMFactory(DeviceFactory):
             # grow the container as large as possible
             if self.container:
                 size += sum(p.size for p in self.container.parents)
-                log.debug("size bumped to %d to include container parents" % size)
+                log.debug("size bumped to %s to include container parents" % size)
 
             size += self._get_free_disk_space()
-            log.debug("size bumped to %d to include free disk space" % size)
+            log.debug("size bumped to %s to include free disk space" % size)
         else:
             # container_size is a request for a fixed size for the container
             size += get_pv_space(self.container_size, len(self.disks))
@@ -1139,14 +1139,14 @@ class LVMFactory(DeviceFactory):
         # this does not apply if a specific container size was requested
         if self.container_size in [SIZE_POLICY_AUTO, SIZE_POLICY_MAX]:
             size += self._get_device_space()
-            log.debug("size bumped to %d to include new device space" % size)
+            log.debug("size bumped to %s to include new device space" % size)
             if self.device and self.container_size == SIZE_POLICY_AUTO:
                 # The member count here uses the container's current member set
                 # since that's the basis for the current device's disk space
                 # usage.
                 size -= get_pv_space(self.device.size,
                    len(self.container.parents))
-                log.debug("size cut to %d to omit old device space" % size)
+                log.debug("size cut to %s to omit old device space" % size)
 
         if self.container_raid_level:
             # add five extents per disk to account for md metadata
@@ -1313,7 +1313,7 @@ class LVMThinPFactory(LVMFactory):
 
         size = self.size
         if free < size:
-            log.info("adjusting size from %.2f to %.2f so it fits "
+            log.info("adjusting size from %s to %s so it fits "
                      "in pool %s" % (size, free, self.pool.name))
             size = free
 
@@ -1365,7 +1365,7 @@ class LVMThinPFactory(LVMFactory):
                                        pesize=self._pesize)
                 log.debug("old device size: %s ; old pad: %s" % (self.device.size, pad))
                 size -= pad
-                log.debug("size cut to %d to omit old device padding" % size)
+                log.debug("size cut to %s to omit old device padding" % size)
 
         return size
 
@@ -1414,7 +1414,7 @@ class LVMThinPFactory(LVMFactory):
 
         log.debug("requested size is %s" % self.size)
         size = self.size    # projected size for the pool (not padded)
-        free = 0            # total space within the vg that is available to us
+        free = Size(bytes=0)# total space within the vg that is available to us
         if self.pool:
             free += self.pool.freeSpace # pools are always auto-sized
             # pool lv sizes go toward projected pool size and vg free space
@@ -1441,7 +1441,7 @@ class LVMThinPFactory(LVMFactory):
         if free < (size + pad):
             pad = int(get_pool_padding(free, pesize=self._pesize, reverse=True))
             free = self.container.align(free - pad) # round down
-            log.info("adjusting pool size from %.2f to %.2f so it fits "
+            log.info("adjusting pool size from %s to %s so it fits "
                      "in container %s" % (size, free, self.container.name))
             size = free
 
@@ -1569,7 +1569,7 @@ class BTRFSFactory(DeviceFactory):
 
     def _get_total_space(self):
         """ Return the total space needed for the specified container. """
-        size = 0
+        size = Size(bytes=0)
         if self.container and self.container.exists:
             return size
 
diff --git a/blivet/devicelibs/crypto.py b/blivet/devicelibs/crypto.py
index bc1e45d..28c03ae 100644
--- a/blivet/devicelibs/crypto.py
+++ b/blivet/devicelibs/crypto.py
@@ -24,8 +24,9 @@ import os
 from pycryptsetup import CryptSetup
 
 from ..errors import *
+from ..size import Size
 
-LUKS_METADATA_SIZE = 2.0    # MB
+LUKS_METADATA_SIZE = Size(en_spec="2 MiB")
 
 # Keep the character set size a power of two to make sure all characters are
 # equally likely
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
index eaf1aa2..37cd13c 100644
--- a/blivet/devicelibs/lvm.py
+++ b/blivet/devicelibs/lvm.py
@@ -23,10 +23,12 @@
 import os
 import math
 import re
+from decimal import Decimal
 
 import logging
 log = logging.getLogger("blivet")
 
+from ..size import Size
 from .. import util
 from .. import arch
 from ..errors import *
@@ -35,14 +37,14 @@ from ..i18n import _
 MAX_LV_SLOTS = 256
 
 # some of lvm's defaults that we have no way to ask it for
-LVM_PE_START = 1.0      # MB
-LVM_PE_SIZE = 4.0       # MB
+LVM_PE_START = Size(en_spec="1 MiB")
+LVM_PE_SIZE = Size(en_spec="4 MiB")
 
 # thinp constants
-LVM_THINP_MIN_METADATA_SIZE = 2             # 2 MiB
-LVM_THINP_MAX_METADATA_SIZE = 16384         # 16 GiB
-LVM_THINP_MIN_CHUNK_SIZE = 0.0625           # 64 KiB
-LVM_THINP_MAX_CHUNK_SIZE = 1024             # 1 GiB
+LVM_THINP_MIN_METADATA_SIZE = Size(en_spec="2 MiB")
+LVM_THINP_MAX_METADATA_SIZE = Size(en_spec="16 GiB")
+LVM_THINP_MIN_CHUNK_SIZE = Size(en_spec="64 KiB")
+LVM_THINP_MAX_CHUNK_SIZE = Size(en_spec="1 GiB")
 
 def has_lvm():
     if util.find_program_in_path("lvm"):
@@ -116,36 +118,39 @@ def blacklistVG(name):
     global lvm_vg_blacklist
     lvm_vg_blacklist.append(name)
 
-def getPossiblePhysicalExtents(floor=0):
-    """Returns a list of integers representing the possible values for
-       the physical extent of a volume group.  Value is in KB.
+def getPossiblePhysicalExtents():
+    """ Returns a list of possible values for physical extent of a volume group.
 
-       floor - size (in KB) of smallest PE we care about.
+        :returns: list of possible extent sizes (:class:`~.size.Size`)
+        :rtype: list
     """
 
     possiblePE = []
-    curpe = 8
-    while curpe <= 16384*1024:
-	if curpe >= floor:
-	    possiblePE.append(curpe)
+    curpe = Size(en_spec="1 KiB")
+    while curpe <= Size(en_spec="16 GiB"):
+	possiblePE.append(curpe)
 	curpe = curpe * 2
 
     return possiblePE
 
 def getMaxLVSize():
-    """ Return the maximum size (in MB) of a logical volume. """
+    """ Return the maximum size of a logical volume. """
     if arch.getArch() in ("x86_64", "ppc64", "alpha", "ia64", "s390"): #64bit architectures
-        return (8*1024*1024*1024*1024) #Max is 8EiB (very large number..)
+        return Size(en_spec="8 EiB")
     else:
-        return (16*1024*1024) #Max is 16TiB
+        return Size(en_spec="16 TiB")
 
 def clampSize(size, pesize, roundup=None):
+    delta = size % pesize
+    if not delta:
+        return size
+
     if roundup:
-        round = math.ceil
+        clamped = size + (pesize - delta)
     else:
-        round = math.floor
+        clamped = size - delta
 
-    return long(round(float(size)/float(pesize)) * pesize)
+    return clamped
 
 def get_pv_space(size, disks, pesize=LVM_PE_SIZE):
     """ Given specs for an LV, return total PV space required. """
@@ -155,8 +160,7 @@ def get_pv_space(size, disks, pesize=LVM_PE_SIZE):
     if size == 0:
         return size
 
-    space = clampSize(size, pesize, roundup=True) + \
-            pesize
+    space = clampSize(size, pesize, roundup=True) + pesize
     return space
 
 def get_pool_padding(size, pesize=LVM_PE_SIZE, reverse=False):
@@ -166,9 +170,9 @@ def get_pool_padding(size, pesize=LVM_PE_SIZE, reverse=False):
         should calculate how much of the total is the pad
     """
     if not reverse:
-        multiplier = 0.2
+        multiplier = Decimal('0.2')
     else:
-        multiplier = 1.0 / 6
+        multiplier = Decimal('1.0') / Decimal('6')
 
     pad = min(clampSize(size * multiplier, pesize, roundup=True),
               clampSize(LVM_THINP_MAX_METADATA_SIZE, pesize, roundup=True))
@@ -176,15 +180,26 @@ def get_pool_padding(size, pesize=LVM_PE_SIZE, reverse=False):
     return pad
 
 def is_valid_thin_pool_metadata_size(size):
-    """ Return True if size (in MiB) is a valid thin pool metadata vol size. """
+    """ Return True if size is a valid thin pool metadata vol size.
+
+        :param size: metadata vol size to validate
+        :type size: :class:`~.size.Size`
+        :returns: whether the size is valid
+        :rtype: bool
+    """
     return (LVM_THINP_MIN_METADATA_SIZE <= size <= LVM_THINP_MAX_METADATA_SIZE)
 
 # To support discard, chunk size must be a power of two. Otherwise it must be a
 # multiple of 64 KiB.
 def is_valid_thin_pool_chunk_size(size, discard=False):
-    """ Return True if size (in MiB) is a valid thin pool chunk size.
-
-        discard (boolean) indicates whether discard support is required
+    """ Return True if size is a valid thin pool chunk size.
+
+        :param size: chunk size to validate
+        :type size: :class:`~.size.Size`
+        :keyword discard: whether discard support is required (default: False)
+        :type discard: bool
+        :returns: whether the size is valid
+        :rtype: bool
     """
     if not LVM_THINP_MIN_CHUNK_SIZE <= size <= LVM_THINP_MAX_CHUNK_SIZE:
         return False
@@ -214,7 +229,7 @@ def pvcreate(device):
 
 def pvresize(device, size):
     args = ["pvresize"] + \
-            ["--setphysicalvolumesize", ("%dm" % size)] + \
+            ["--setphysicalvolumesize", ("%dm" % size.convertTo(en_spec="mib"))] + \
             _getConfigArgs() + \
             [device]
 
@@ -279,7 +294,7 @@ def pvinfo(device):
 def vgcreate(vg_name, pv_list, pe_size):
     argv = ["vgcreate"]
     if pe_size:
-        argv.extend(["-s", "%dm" % pe_size])
+        argv.extend(["-s", "%dm" % pe_size.convertTo(en_spec="mib")])
     argv.extend(_getConfigArgs())
     argv.append(vg_name)
     argv.extend(pv_list)
@@ -393,7 +408,7 @@ def lvorigin(vg_name, lv_name):
 
 def lvcreate(vg_name, lv_name, size, pvs=[]):
     args = ["lvcreate"] + \
-            ["-L", "%dm" % size] + \
+            ["-L", "%dm" % size.convertTo(en_spec="mib")] + \
             ["-n", lv_name] + \
             _getConfigArgs() + \
             [vg_name] + pvs
@@ -415,7 +430,7 @@ def lvremove(vg_name, lv_name):
 
 def lvresize(vg_name, lv_name, size):
     args = ["lvresize"] + \
-            ["--force", "-L", "%dm" % size] + \
+            ["--force", "-L", "%dm" % size.convertTo(en_spec="mib")] + \
             _getConfigArgs() + \
             ["%s/%s" % (vg_name, lv_name)]
 
@@ -447,15 +462,15 @@ def lvdeactivate(vg_name, lv_name):
 
 def thinpoolcreate(vg_name, lv_name, size, metadatasize=None, chunksize=None):
     args = ["lvcreate", "--thinpool", "%s/%s" % (vg_name, lv_name),
-            "--size", "%dm" % size]
+            "--size", "%dm" % size.convertTo(en_spec="mib")]
 
     if metadatasize:
         # default unit is MiB
-        args += ["--poolmetadatasize", "%d" % metadatasize]
+        args += ["--poolmetadatasize", "%d" % metadatasize.convertTo(en_spec="mib")]
 
     if chunksize:
         # default unit is KiB
-        args += ["--chunksize", "%d" % (chunksize * 1024,)]
+        args += ["--chunksize", "%d" % chunksize.convertTo(en_spec="kib")]
 
     args += _getConfigArgs()
 
diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py
index 7cab43a..59e1b0e 100644
--- a/blivet/devicelibs/mdraid.py
+++ b/blivet/devicelibs/mdraid.py
@@ -24,14 +24,15 @@ import os
 
 from .. import util
 from ..errors import *
+from ..size import Size
 from . import raid
 
 import logging
 log = logging.getLogger("blivet")
 
 # these defaults were determined empirically
-MD_SUPERBLOCK_SIZE = 2.0    # MB
-MD_CHUNK_SIZE = 0.5         # MB
+MD_SUPERBLOCK_SIZE = Size(en_spec="2 MiB")
+MD_CHUNK_SIZE = Size(en_spec="512 KiB")
 
 class MDRaidLevels(raid.RAIDLevels):
     @classmethod
@@ -75,8 +76,13 @@ def get_raid_superblock_size(size, version=None):
     """ mdadm has different amounts of space reserved for its use depending
     on the metadata type and size of the array.
 
-    0.9 use 2.0 MB
-    1.0 use 2.0 MB
+    :param size: size of the array
+    :type size: :class:`~.size.Size`
+    :param version: metadata version
+    :type version: str
+
+    0.9 use 2.0 MiB
+    1.0 use 2.0 MiB
     1.1 or 1.2 use the formula lifted from mdadm/super1.c to calculate it
     based on the array size.
     """
@@ -88,11 +94,14 @@ def get_raid_superblock_size(size, version=None):
         # MDADM: We try to leave 0.1% at the start for reshape
         # 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 MB
-        headroom = 128
-        while headroom << 10 > size:
+        # NOTE: In the mdadm code this is in 512b sectors. Converted to use MiB
+        headroom = int(Size(en_spec="128 MiB"))
+        while headroom << 10 > size and headroom > Size(en_spec="1 MiB"):
             headroom >>= 1
-    log.info("Using %sMB superBlockSize" % (headroom))
+
+        headroom = Size(bytes=headroom)
+
+    log.info("Using %s superBlockSize" % (headroom))
     return headroom
 
 def mdadm(args):
diff --git a/blivet/devicelibs/raid.py b/blivet/devicelibs/raid.py
index b55804c..0c277d1 100644
--- a/blivet/devicelibs/raid.py
+++ b/blivet/devicelibs/raid.py
@@ -24,6 +24,7 @@
 import abc
 
 from ..errors import RaidError
+from ..size import Size
 
 def div_up(a,b):
     """Rounds up integer division."""
@@ -95,7 +96,7 @@ class RAIDLevel(object):
         """Return the required size for each member of the array for
            storing only data.
            :param size: size of data to be stored
-           :type size: natural number
+           :type size: :class:`~.size.Size`
 
            :param member_count: number of members in this array
            :param member_count: int
@@ -114,16 +115,15 @@ class RAIDLevel(object):
         raise NotImplementedError()
 
     def get_raw_array_size(self, member_count, smallest_member_size):
-        """Calculate the raw arraysize, i.e., the number of MB available.
+        """Calculate the raw arraysize, i.e., the available space.
 
            :param member_count: the number of members in the array
-           :param type: int
-           :param smallest_member_size: the size (MB) of the smallest
+           :type member_count: int
+           :param smallest_member_size: the size of the smallest
              member of this array
-           :param type: int
-
-           The return value has the same units as the smallest_member_size
-           parameter.
+           :type smallest_member_size: :class:`~.size.Size`
+           :returns: the array size, not including metadata or chunk size
+           :rtype: :class:`~.size.Size`
         """
         if member_count < self.min_members:
             raise RaidError("%s requires at least %d disks" % (self.name, self.min_members))
@@ -266,7 +266,8 @@ class RAID0(RAIDLevel):
         return div_up(size, member_count)
 
     def _get_raw_array_size(self, member_count, smallest_member_size):
-        return member_count * smallest_member_size
+        # smallest_member_size dictates the return type
+        return smallest_member_size * member_count
 
     def _get_size(self, size, chunk_size):
         return size - size % chunk_size
@@ -312,7 +313,8 @@ class RAID4(RAIDLevel):
         return div_up(size, member_count - 1)
 
     def _get_raw_array_size(self, member_count, smallest_member_size):
-        return (member_count - 1) * smallest_member_size
+        # smallest_member_size dictates the return type
+        return smallest_member_size * (member_count - 1)
 
     def _get_size(self, size, chunk_size):
         return size - size % chunk_size
@@ -335,7 +337,8 @@ class RAID5(RAIDLevel):
         return div_up(size, (member_count - 1))
 
     def _get_raw_array_size(self, member_count, smallest_member_size):
-        return (member_count - 1) * smallest_member_size
+        # smallest_member_size dictates the return type
+        return smallest_member_size * (member_count - 1)
 
     def _get_size(self, size, chunk_size):
         return size - size % chunk_size
@@ -358,7 +361,8 @@ class RAID6(RAIDLevel):
         return div_up(size, member_count - 2)
 
     def _get_raw_array_size(self, member_count, smallest_member_size):
-        return (member_count - 2) * smallest_member_size
+        # smallest_member_size dictates the return type
+        return smallest_member_size * (member_count - 2)
 
     def _get_size(self, size, chunk_size):
         return size - size % chunk_size
@@ -381,7 +385,8 @@ class RAID10(RAIDLevel):
         return div_up(size, (member_count // 2))
 
     def _get_raw_array_size(self, member_count, smallest_member_size):
-        return (member_count // 2) * smallest_member_size
+        # smallest_member_size dictates the return type
+        return smallest_member_size * (member_count // 2)
 
     def _get_size(self, size, chunk_size):
         return size
diff --git a/blivet/devicelibs/swap.py b/blivet/devicelibs/swap.py
index 31f86f3..feed4fe 100644
--- a/blivet/devicelibs/swap.py
+++ b/blivet/devicelibs/swap.py
@@ -22,16 +22,18 @@
 
 import resource
 import os
+from decimal import Decimal
 
 from ..errors import *
 from .. import util
 from . import dm
+from ..size import Size
 
 import logging
 log = logging.getLogger("blivet")
 
 # maximum ratio of swap size to disk size (10 %)
-MAX_SWAP_DISK_RATIO = 0.1
+MAX_SWAP_DISK_RATIO = Decimal('0.1')
 
 def mkswap(device, label=''):
     # We use -f to force since mkswap tends to refuse creation on lvs with
@@ -130,42 +132,47 @@ def swapSuggestion(quiet=False, hibernation=False, disk_space=None):
 
     """
 
-    mem = util.total_memory()/1024
+    mem = util.total_memory()
     mem = ((mem/16)+1)*16
     if not quiet:
-        log.info("Detected %sM of memory", mem)
+        log.info("Detected %s of memory", mem)
+
+    two_GiB = Size(en_spec="2GiB")
+    four_GiB = Size(en_spec="4GiB")
+    eight_GiB = Size(en_spec="8GiB")
+    sixtyfour_GiB = Size(en_spec="64 GiB")
 
     #chart suggested in the discussion with other teams
-    if mem < 2048:
+    if mem < two_GiB:
         swap = 2 * mem
 
-    elif 2048 <= mem < 8192:
+    elif two_GiB <= mem < eight_GiB:
         swap = mem
 
-    elif 8192 <= mem < 65536:
+    elif eight_GiB <= mem < sixtyfour_GiB:
         swap = mem / 2
 
     else:
-        swap = 4096
+        swap = four_GiB
 
     if hibernation:
-        if mem <= 65536:
+        if mem <= sixtyfour_GiB:
             swap = mem + swap
         else:
-            log.info("Ignoring --hibernation option on systems with 64 GB of RAM or more")
+            log.info("Ignoring --hibernation option on systems with %s of RAM or more", sixtyfour_GiB)
 
     if disk_space is not None and not hibernation:
-        max_swap = int(disk_space * MAX_SWAP_DISK_RATIO)
+        max_swap = disk_space * MAX_SWAP_DISK_RATIO
         if swap > max_swap:
-            log.info("Suggested swap size (%(swap)d M) exceeds %(percent)d %% of "
-                     "disk space, using %(percent)d %% of disk space (%(size)d M) "
+            log.info("Suggested swap size (%(swap)s) exceeds %(percent)d %% of "
+                     "disk space, using %(percent)d %% of disk space (%(size)s) "
                      "instead." % {"percent": MAX_SWAP_DISK_RATIO*100,
                                    "swap": swap,
                                    "size": max_swap})
             swap = max_swap
 
     if not quiet:
-        log.info("Swap attempt of %sM", swap)
+        log.info("Swap attempt of %s", swap)
 
     return swap
 
diff --git a/blivet/devices.py b/blivet/devices.py
index 24f3423..bdcca42 100644
--- a/blivet/devices.py
+++ b/blivet/devices.py
@@ -21,10 +21,10 @@
 #
 
 import os
-import math
 import copy
 import pprint
 import tempfile
+from decimal import Decimal
 
 # device backend modules
 from devicelibs import mdraid
@@ -44,6 +44,7 @@ from flags import flags
 from storage_log import log_method_call
 from udev import *
 from formats import get_device_format_class, getFormat, DeviceFormat
+from size import Size
 from i18n import P_
 
 import logging
@@ -395,8 +396,8 @@ class StorageDevice(Device):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -458,13 +459,13 @@ class StorageDevice(Device):
                 sector_size = read_int_from_sys("%s/queue/logical_block_size"
                                                 % device_root)
                 size = read_int_from_sys("%s/size" % device_root)
-                self._size = (size * sector_size) / (1024.0 * 1024.0)
+                self._size = Size(bytes=(size * sector_size))
 
     def __str__(self):
         exist = "existing"
         if not self.exists:
             exist = "non-existent"
-        s = "%s %dMB %s" % (exist, self.size, super(StorageDevice, self).__str__())
+        s = "%s %s %s" % (exist, self.size, super(StorageDevice, self).__str__())
         if self.format.type:
             s += " with %s" % self.format
 
@@ -804,7 +805,7 @@ class StorageDevice(Device):
                 _format.setup()
 
     def _getSize(self):
-        """ Get the device's size in MB, accounting for pending changes. """
+        """ Get the device's size, accounting for pending changes. """
         if self.exists and not self.mediaPresent:
             return 0
 
@@ -820,13 +821,13 @@ class StorageDevice(Device):
     def _setSize(self, newsize):
         """ Set the device's size to a new value. """
         if newsize > self.maxSize:
-            raise DeviceError("device cannot be larger than %s MB" %
+            raise DeviceError("device cannot be larger than %s" %
                               (self.maxSize,), self.name)
         self._size = newsize
 
     size = property(lambda x: x._getSize(),
                     lambda x, y: x._setSize(y),
-                    doc="The device's size in MB, accounting for pending changes")
+                    doc="The device's size, accounting for pending changes")
 
     @property
     def currentSize(self):
@@ -838,7 +839,7 @@ class StorageDevice(Device):
         """
         size = 0
         if self.exists and self.partedDevice:
-            size = self.partedDevice.getSize()
+            size = Size(bytes=self.partedDevice.getLength(unit="B"))
         elif self.exists:
             size = self._size
         return size
@@ -987,8 +988,8 @@ class DiskDevice(StorageDevice):
         """
             :param name: the device name (generally a device node's basename)
             :type name: str
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -1033,7 +1034,7 @@ class DiskDevice(StorageDevice):
         # Some drivers (cpqarray <blegh>) make block device nodes for
         # controllers with no disks attached and then report a 0 size,
         # treat this as no media present
-        return self.partedDevice.getSize() != 0
+        return self.partedDevice.getLength(unit="B") != 0
 
     @property
     def description(self):
@@ -1041,9 +1042,8 @@ class DiskDevice(StorageDevice):
 
     @property
     def size(self):
-        """ The disk's size in MB """
+        """ The disk's size """
         return super(DiskDevice, self).size
-    #size = property(StorageDevice._getSize)
 
     def _preDestroy(self):
         """ Destroy the device. """
@@ -1066,7 +1066,7 @@ class PartitionDevice(StorageDevice):
     """
     _type = "partition"
     _resizable = True
-    defaultSize = 500
+    defaultSize = Size(en_spec="500MiB")
 
     def __init__(self, name, format=None,
                  size=None, grow=False, maxsize=None, start=None, end=None,
@@ -1078,8 +1078,8 @@ class PartitionDevice(StorageDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class::class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -1101,8 +1101,8 @@ class PartitionDevice(StorageDevice):
             :type partType: parted partition type constant
             :keyword grow: whether or not to grow the partition
             :type grow: bool
-            :keyword maxsize: max size for growable partitions in MB
-            :type maxsize: int or float
+            :keyword maxsize: max size for growable partitions
+            :type maxsize: :class:`~.size.Size`
             :keyword start: start sector (see note, below)
             :type start: long
             :keyword end: end sector (see note, below)
@@ -1470,8 +1470,7 @@ class PartitionDevice(StorageDevice):
         if not self.exists:
             return
 
-        # this is in MB
-        self._size = self.partedPartition.getSize()
+        self._size = Size(bytes=self.partedPartition.getLength(unit="B"))
         self._currentSize = self._size
         self.targetSize = self._size
 
@@ -1489,7 +1488,7 @@ class PartitionDevice(StorageDevice):
         device = self.partedPartition.geometry.device.path
 
         # Erase 1MiB or to end of partition
-        count = 1 * 1024 * 1024 / bs
+        count = Size(en_spec="1 MiB") / bs
         count = min(count, part_len)
 
         cmd = ["dd", "if=/dev/zero", "of=%s" % device, "bs=%s" % bs,
@@ -1533,7 +1532,7 @@ class PartitionDevice(StorageDevice):
             DeviceFormat(device=self.path, exists=True).destroy()
 
         StorageDevice._postCreate(self)
-        self._currentSize = self.partedPartition.getSize()
+        self._currentSize = Size(bytes=self.partedPartition.getLength(unit="B"))
 
     def create(self):
         """ Create the device. """
@@ -1554,7 +1553,7 @@ class PartitionDevice(StorageDevice):
         # compute new size for partition
         currentGeom = partition.geometry
         currentDev = currentGeom.device
-        newLen = long(self.targetSize * 1024 * 1024) / currentDev.sectorSize
+        newLen = self.targetSize / currentDev.sectorSize
         newGeometry = parted.Geometry(device=currentDev,
                                       start=currentGeom.start,
                                       length=newLen)
@@ -1582,7 +1581,7 @@ class PartitionDevice(StorageDevice):
                                         end=geometry.end)
 
         self.disk.format.commit()
-        self._currentSize = partition.getSize()
+        self._currentSize = Size(bytes=partition.getLength(unit="B"))
 
     def _preDestroy(self):
         StorageDevice._preDestroy(self)
@@ -1631,8 +1630,7 @@ class PartitionDevice(StorageDevice):
         """ Get the device's size. """
         size = self._size
         if self.partedPartition:
-            # this defaults to MB
-            size = self.partedPartition.getSize()
+            size = Size(bytes=self.partedPartition.getLength(unit="B"))
         return size
 
     def _setSize(self, newsize):
@@ -1640,7 +1638,7 @@ class PartitionDevice(StorageDevice):
 
             Arguments:
 
-                newsize -- the new size (in MB)
+                newsize -- the new size
 
         """
         log_method_call(self, self.name,
@@ -1651,8 +1649,7 @@ class PartitionDevice(StorageDevice):
         if newsize > self.disk.size:
             raise ValueError("partition size would exceed disk size")
 
-        # this defaults to MB
-        maxAvailableSize = self.partedPartition.getMaxAvailableSize()
+        maxAvailableSize = Size(bytes=self.partedPartition.getMaxAvailableSize(unit="B"))
 
         if newsize > maxAvailableSize:
             raise ValueError("new size is greater than available space")
@@ -1661,7 +1658,7 @@ class PartitionDevice(StorageDevice):
         geometry = self.partedPartition.geometry
         physicalSectorSize = geometry.device.physicalSectorSize
 
-        new_length = (newsize * (1024 * 1024)) / physicalSectorSize
+        new_length = newsize / physicalSectorSize
         geometry.length = new_length
 
     def _getDisk(self):
@@ -1706,7 +1703,7 @@ class PartitionDevice(StorageDevice):
             pass
         else:
             if partition.type == parted.PARTITION_FREESPACE:
-                maxPartSize = self.size + math.floor(partition.getSize())
+                maxPartSize = self.size + partition.getLength(unit="B")
 
         return min(self.format.maxSize, maxPartSize)
 
@@ -1750,7 +1747,7 @@ class PartitionDevice(StorageDevice):
             data.size = int(self.req_base_size)
             data.grow = self.req_grow
             if self.req_grow:
-                data.maxSizeMB = self.req_max_size
+                data.maxSizeMB = int(self.req_max_size.convertTo(en_spec="mib"))
 
             ##data.disk = self.disk.name                      # by-id
             if self.req_disks and len(self.req_disks) == 1:
@@ -1774,8 +1771,8 @@ class DMDevice(StorageDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -1893,8 +1890,8 @@ class DMLinearDevice(DMDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -1958,8 +1955,8 @@ class DMCryptDevice(DMDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -1984,7 +1981,7 @@ class LUKSDevice(DMCryptDevice):
             :keyword exists: does this device exist?
             :type exists: bool
             :keyword size: the device's size
-            :type size: int or float
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -2001,9 +1998,9 @@ class LUKSDevice(DMCryptDevice):
     @property
     def size(self):
         if not self.exists or not self.partedDevice:
-            size = float(self.slave.size) - crypto.LUKS_METADATA_SIZE
+            size = self.slave.size - crypto.LUKS_METADATA_SIZE
         else:
-            size = self.partedDevice.getSize()
+            size = Size(self.partedDevice.getLength(unit="B"))
         return size
 
     def _postCreate(self):
@@ -2048,14 +2045,14 @@ class LVMVolumeGroupDevice(DMDevice):
             :keyword sysfsPath: sysfs device path
             :type sysfsPath: str
             :keyword peSize: physical extent size
-            :type peSize: int or float
+            :type peSize: :class:`~.size.Size`
 
             For existing VG's only:
 
             :keyword size: the VG's size
-            :type size: int or float
+            :type size: :class:`~.size.Size`
             :keyword free -- amount of free space in the VG
-            :type free: int or float
+            :type free: :class:`~.size.Size`
             :keyword peFree: number of free extents
             :type peFree: int
             :keyword peCount -- total number of extents
@@ -2092,7 +2089,7 @@ class LVMVolumeGroupDevice(DMDevice):
         self.lv_types = []
         self.hasDuplicate = False
         self.reserved_percent = 0
-        self.reserved_space = 0
+        self.reserved_space = Size(bytes=0)
 
         # this will have to be covered by the 20% pad for non-existent pools
         self.poolMetaData = 0
@@ -2102,7 +2099,7 @@ class LVMVolumeGroupDevice(DMDevice):
 
         # TODO: validate peSize if given
         if not self.peSize:
-            self.peSize = lvm.LVM_PE_SIZE  # MB
+            self.peSize = lvm.LVM_PE_SIZE
 
         if not self.exists:
             self.pvCount = len(self.parents)
@@ -2302,7 +2299,7 @@ class LVMVolumeGroupDevice(DMDevice):
            lv.size > self.freeSpace:
             raise DeviceError("new lv is too large to fit in free space", self.name)
 
-        log.debug("Adding %s/%dMB to %s" % (lv.name, lv.size, self.name))
+        log.debug("Adding %s/%s to %s" % (lv.name, lv.size, self.name))
         self._lvs.append(lv)
 
     def _removeLogVol(self, lv):
@@ -2380,10 +2377,10 @@ class LVMVolumeGroupDevice(DMDevice):
 
     @property
     def reservedSpace(self):
-        """ Reserved space in this VG, in MB """
-        reserved = 0
+        """ Reserved space in this VG """
+        reserved = Size(0)
         if self.reserved_percent > 0:
-            reserved = self.reserved_percent * 0.01 * self.size
+            reserved = self.reserved_percent * Decimal('0.01') * self.size
         elif self.reserved_space > 0:
             reserved = self.reserved_space
 
@@ -2406,41 +2403,33 @@ class LVMVolumeGroupDevice(DMDevice):
         """ Number of extents in this VG """
         # TODO: just ask lvm if isModified returns False
 
-        return self.size / self.peSize
+        return int(self.size / self.peSize)
 
     @property
     def freeSpace(self):
-        """ The amount of free space in this VG (in MB). """
+        """ The amount of free space in this VG. """
         # TODO: just ask lvm if isModified returns False
 
         # total the sizes of any LVs
-        log.debug("%s size is %dMB" % (self.name, self.size))
+        log.debug("%s size is %s" % (self.name, self.size))
         used = sum(lv.vgSpaceUsed for lv in self.lvs) + self.snapshotSpace
         used += self.reservedSpace
         used += self.poolMetaData
         free = self.size - used
-        log.debug("vg %s has %dMB free" % (self.name, free))
+        log.debug("vg %s has %s free" % (self.name, free))
         return free
 
     @property
     def freeExtents(self):
         """ The number of free extents in this VG. """
         # TODO: just ask lvm if isModified returns False
-        return self.freeSpace / self.peSize
+        return int(self.freeSpace / self.peSize)
 
     def align(self, size, roundup=None):
         """ Align a size to a multiple of physical extent size. """
         size = util.numeric_type(size)
 
-        if roundup:
-            round = math.ceil
-        else:
-            round = math.floor
-
-        # we want Kbytes as a float for our math
-        size *= 1024.0
-        pesize = self.peSize * 1024.0
-        return long((round(size / pesize) * pesize) / 1024)
+        return lvm.clampSize(size, self.peSize, roundup=roundup)
 
     @property
     def pvs(self):
@@ -2477,7 +2466,7 @@ class LVMVolumeGroupDevice(DMDevice):
         data.physvols = ["pv.%d" % p.id for p in self.parents]
         data.preexist = self.exists
         if not self.exists:
-            data.pesize = self.peSize * 1024
+            data.pesize = self.peSize.convertTo(en_spec="KiB")
 
         # reserved percent/space
 
@@ -2498,8 +2487,8 @@ class LVMLogicalVolumeDevice(DMDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -2514,9 +2503,9 @@ class LVMLogicalVolumeDevice(DMDevice):
             :keyword copies: number of copies in the vg (>1 for mirrored lvs)
             :type copies: int
             :keyword logSize: size of log volume (for mirrored lvs)
-            :type logSize: int or float
+            :type logSize: :class:`~.size.Size`
             :keyword snapshotSpace: sum of sizes of snapshots of this lv
-            :type snapshotSpace: int or float
+            :type snapshotSpace: :class:`~.size.Size`
             :keyword singlePV: if true, maps this lv to a single pv
             :type singlePV: bool
             :keyword segType: segment type (eg: "linear", "raid1")
@@ -2527,7 +2516,7 @@ class LVMLogicalVolumeDevice(DMDevice):
             :keyword grow: whether to grow this LV
             :type grow: bool
             :keyword maxsize: maximum size for growable LV
-            :type maxsize: int or float
+            :type maxsize: :class:`~.size.Size`
             :keyword percent -- percent of VG space to take
             :type percent: int
 
@@ -2547,7 +2536,7 @@ class LVMLogicalVolumeDevice(DMDevice):
         self.singlePVerr = ("%(mountpoint)s is restricted to a single "
                             "physical volume on this platform.  No physical "
                             "volumes available in volume group %(vgname)s "
-                            "with %(size)d MB of available space." %
+                            "with %(size)s of available space." %
                            {'mountpoint': getattr(self.format, "mountpoint",
                                                   "A proposed logical volume"),
                             'vgname': self.vg.name,
@@ -2590,8 +2579,8 @@ class LVMLogicalVolumeDevice(DMDevice):
         s += ("  VG device = %(vgdev)r\n"
               "  segment type = %(type)s percent = %(percent)s\n"
               "  mirror copies = %(copies)d"
-              "  snapshot total =  %(snapshots)dMB\n"
-              "  VG space used = %(vgspace)dMB" %
+              "  snapshot total =  %(snapshots)s\n"
+              "  VG space used = %(vgspace)s" %
               {"vgdev": self.vg, "percent": self.req_percent,
                "copies": self.copies, "type": self.segType,
                "snapshots": self.snapshotSpace, "vgspace": self.vgSpaceUsed })
@@ -2615,12 +2604,12 @@ class LVMLogicalVolumeDevice(DMDevice):
 
     def _setSize(self, size):
         size = self.vg.align(util.numeric_type(size))
-        log.debug("trying to set lv %s size to %dMB" % (self.name, size))
+        log.debug("trying to set lv %s size to %s" % (self.name, size))
         if size <= self.vg.freeSpace + self.vgSpaceUsed:
             self._size = size
             self.targetSize = size
         else:
-            log.debug("failed to set size: %dMB short" % (size - (self.vg.freeSpace + self.vgSpaceUsed),))
+            log.debug("failed to set size: %s short" % (size - (self.vg.freeSpace + self.vgSpaceUsed),))
             raise ValueError("not enough free space in volume group")
 
     size = property(StorageDevice._getSize, _setSize)
@@ -2780,7 +2769,7 @@ class LVMLogicalVolumeDevice(DMDevice):
             data.grow = self.req_grow
             if self.req_grow:
                 data.size = int(self.req_size)
-                data.maxSizeMB = self.req_max_size
+                data.maxSizeMB = self.req_max_size.convertTo(en_spec="mib")
             else:
                 data.size = int(self.size)
 
@@ -2802,8 +2791,8 @@ class LVMThinPoolDevice(LVMLogicalVolumeDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -2820,13 +2809,13 @@ class LVMThinPoolDevice(LVMLogicalVolumeDevice):
             :keyword grow: whether to grow this LV
             :type grow: bool
             :keyword maxsize: maximum size for growable LV
-            :type maxsize: int or float
+            :type maxsize: :class:`~.size.Size`
             :keyword percent: percent of VG space to take
             :type percent: int
             :keyword metadatasize: the size of the metadata LV
-            :type metadatasize: int or float
+            :type metadatasize: :class:`~.size.Size`
             :keyword chunksize: chunk size for the pool
-            :type chunksize: int or float
+            :type chunksize: :class:`~.size.Size`
         """
         if metadatasize is not None and \
            not lvm.is_valid_thin_pool_metadata_size(metadatasize):
@@ -2855,7 +2844,7 @@ class LVMThinPoolDevice(LVMLogicalVolumeDevice):
 
         # TODO: add some checking to prevent overcommit for preexisting
         self.vg._addLogVol(lv)
-        log.debug("Adding %s/%dMB to %s" % (lv.name, lv.size, self.name))
+        log.debug("Adding %s/%s to %s" % (lv.name, lv.size, self.name))
         self._lvs.append(lv)
 
     def _removeLogVol(self, lv):
@@ -2962,8 +2951,8 @@ class MDRaidArrayDevice(StorageDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -3001,7 +2990,7 @@ class MDRaidArrayDevice(StorageDevice):
         self._totalDevices = util.numeric_type(totalDevices)
         self.memberDevices = util.numeric_type(memberDevices)
 
-        self.chunkSize = 512.0 / 1024.0         # chunk size in MB
+        self.chunkSize = mdraid.MD_CHUNK_SIZE
 
         if not self.exists and not isinstance(metadataVersion, str):
             self.metadataVersion = "default"
@@ -3058,7 +3047,7 @@ class MDRaidArrayDevice(StorageDevice):
         This is used to calculate the superBlockSize for v1.1 and v1.2
         metadata.
 
-        Returns the raw size in MB
+        Returns the raw size
 
         Raises an MDRaidError if this operation is not meaningful for the
         raid level.
@@ -3109,7 +3098,7 @@ class MDRaidArrayDevice(StorageDevice):
                 size = 0
             log.debug("non-existent RAID %s size == %s" % (self.level, size))
         else:
-            size = self.partedDevice.getSize()
+            size = Size(bytes=self.partedDevice.getLength(unit="B"))
             log.debug("existing RAID %s size == %s" % (self.level, size))
 
         return size
@@ -3498,8 +3487,8 @@ class DMRaidArrayDevice(DMDevice):
         """
             :param name: the device name (generally a device node's basename)
             :type name: str
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -3611,8 +3600,8 @@ class MultipathDevice(DMDevice):
         """
             :param name: the device name (generally a device node's basename)
             :type name: str
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -3797,8 +3786,8 @@ class FileDevice(StorageDevice):
             :type path: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -3853,9 +3842,18 @@ class FileDevice(StorageDevice):
         """ Create the device. """
         log_method_call(self, self.name, status=self.status)
         fd = os.open(self.path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC)
-        buf = "\0" * 1024 * 1024
-        for n in range(self.size):
-            os.write(fd, buf)
+        # all this fuss is so we write the zeros 1MiB at a time
+        zero = "\0"
+        MiB = Size(en_spec="1 MiB")
+        count = int(self.size.convertTo(en_spec="MiB"))
+        rem = self.size % MiB
+        for n in range(count):
+            os.write(fd, zero * MiB)
+
+        if rem:
+            # write out however many more zeros it takes to hit our size target
+            os.write(fd, zero * rem)
+
         os.close(fd)
 
     def _destroy(self):
@@ -3872,7 +3870,7 @@ class SparseFileDevice(FileDevice):
         """Create a sparse file."""
         log_method_call(self, self.name, status=self.status)
         fd = os.open(self.path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC)
-        os.ftruncate(fd, 1024*1024*self.size)
+        os.ftruncate(fd, self.size)
         os.close(fd)
 
 
@@ -3900,8 +3898,8 @@ class LoopDevice(StorageDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -3983,8 +3981,8 @@ class iScsiDiskDevice(DiskDevice, NetworkStorageDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -4071,8 +4069,8 @@ class FcoeDiskDevice(DiskDevice, NetworkStorageDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -4164,8 +4162,8 @@ class ZFCPDiskDevice(DiskDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
@@ -4207,8 +4205,8 @@ class DASDDevice(DiskDevice):
             :type name: str
             :keyword exists: does this device exist?
             :type exists: bool
-            :keyword size: the device's size in MB
-            :type size: int or float
+            :keyword size: the device's size
+            :type size: :class:`~.size.Size`
             :keyword parents: a list of parent devices
             :type parents: list of :class:`StorageDevice`
             :keyword format: this device's formatting
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index 80f52b6..f582f00 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -49,6 +49,7 @@ from storage_log import log_method_call, log_method_return
 import parted
 import _ped
 from i18n import _
+from size import Size
 
 import logging
 log = logging.getLogger("blivet")
@@ -1314,7 +1315,7 @@ class DeviceTree(object):
                                         "found" % (name, origin_device_name))
                             return
 
-                log.debug("adding %dMB to %s snapshot total"
+                log.debug("adding %s to %s snapshot total"
                             % (lv_sizes[index], origin.name))
                 origin.snapshotSpace += lv_size
                 return
@@ -1391,7 +1392,7 @@ class DeviceTree(object):
         lv_real_names = [n.replace("[", "").replace("]", "") for n in lv_names]
         raid = dict([("%s-%s" % (vg_device.name,
                                  n.replace("[", "").replace("]", "")),
-                      {"copies": 0, "log": 0, "meta": 0})
+                      {"copies": 0, "log": Size(bytes=0), "meta": Size(bytes=0)})
                      for n in lv_names])
         lv_data = zip(lv_names, lv_uuids, lv_attrs, lv_sizes, lv_types)
         for i in range(len(lv_data)):
@@ -1406,8 +1407,8 @@ class DeviceTree(object):
             lv_dev.copies = data["copies"] or 1
             lv_dev.metaDataSize = data["meta"]
             lv_dev.logSize = data["log"]
-            log.debug("set %s copies to %d, metadata size to %dMB, log size "
-                      "to %dMB, total size %dMB"
+            log.debug("set %s copies to %d, metadata size to %s, log size "
+                      "to %s, total size %s"
                         % (lv_dev.name, lv_dev.copies, lv_dev.metaDataSize,
                            lv_dev.logSize, lv_dev.vgSpaceUsed))
 
diff --git a/blivet/formats/__init__.py b/blivet/formats/__init__.py
index 5e0ea32..fd2e4ef 100644
--- a/blivet/formats/__init__.py
+++ b/blivet/formats/__init__.py
@@ -32,6 +32,7 @@ from ..devicelibs.dm import dm_node_from_name
 from ..devicelibs.mdraid import md_node_from_name
 from ..udev import udev_device_get_major, udev_device_get_minor
 from ..i18n import _, N_
+from ..size import Size
 
 import logging
 log = logging.getLogger("blivet")
@@ -159,8 +160,8 @@ class DeviceFormat(object):
     _packages = []                      # required packages
     _services = []                      # required services
     _resizable = False                  # can be resized
-    _maxSize = 0                        # maximum size in MB
-    _minSize = 0                        # minimum size in MB
+    _maxSize = Size(bytes=0)            # maximum size
+    _minSize = Size(bytes=0)            # minimum size
     _dump = False
     _check = False
     _hidden = False                     # hide devices with this formatting?
@@ -446,12 +447,12 @@ class DeviceFormat(object):
 
     @property
     def maxSize(self):
-        """ Maximum size (in MB) for this format type. """
+        """ Maximum size for this format type. """
         return self._maxSize
 
     @property
     def minSize(self):
-        """ Minimum size (in MB) for this format type. """
+        """ Minimum size for this format type. """
         return self._minSize
 
     @property
diff --git a/blivet/formats/biosboot.py b/blivet/formats/biosboot.py
index 5ed0305..3934178 100644
--- a/blivet/formats/biosboot.py
+++ b/blivet/formats/biosboot.py
@@ -23,6 +23,7 @@
 from parted import PARTITION_BIOS_GRUB
 
 from ..errors import *
+from ..size import Size
 from .. import platform
 from ..i18n import N_
 from . import DeviceFormat, register_device_format
@@ -35,8 +36,8 @@ class BIOSBoot(DeviceFormat):
     partedFlag = PARTITION_BIOS_GRUB
     _formattable = True                 # can be formatted
     _linuxNative = True                 # for clearpart
-    _maxSize = 2                        # maximum size in MB
-    _minSize = 0.5                      # minimum size in MB
+    _maxSize = Size(en_spec="2 MiB")
+    _minSize = Size(en_spec="512 KiB")
 
     def __init__(self, *args, **kwargs):
         """
diff --git a/blivet/formats/disklabel.py b/blivet/formats/disklabel.py
index 79d6680..8071abb 100644
--- a/blivet/formats/disklabel.py
+++ b/blivet/formats/disklabel.py
@@ -32,6 +32,7 @@ from ..flags import flags
 from ..udev import udev_settle
 from ..i18n import _, N_
 from . import DeviceFormat, register_device_format
+from ..size import Size
 
 import logging
 log = logging.getLogger("blivet")
@@ -219,7 +220,7 @@ class DiskLabel(DeviceFormat):
         size = self._size
         if not size:
             try:
-                size = self.partedDevice.getSize(unit="MB")
+                size = Size(bytes=self.partedDevice.getLength(unit="B"))
             except Exception:
                 size = 0
 
@@ -410,8 +411,8 @@ class DiskLabel(DeviceFormat):
             return int(open(path).readline().strip())
 
         try:
-            free = sum([f.getSize()
-                        for f in self.partedDisk.getFreeSpacePartitions()])
+            free = sum(Size(bytes=f.getLength(unit="B"))
+                        for f in self.partedDisk.getFreeSpacePartitions())
         except Exception:
             sys_block_root = "/sys/class/block/"
 
@@ -428,7 +429,7 @@ class DiskLabel(DeviceFormat):
                 partition_length = read_int_from_sys("%s/size" % partition_root)
                 used_sectors += partition_length
 
-            free = ((disk_length - used_sectors) * sector_size) / (1024.0 * 1024.0)
+            free = Size(bytes=((disk_length - used_sectors) * sector_size))
 
         return free
 
diff --git a/blivet/formats/dmraid.py b/blivet/formats/dmraid.py
index 875a4ce..c22ea69 100644
--- a/blivet/formats/dmraid.py
+++ b/blivet/formats/dmraid.py
@@ -53,8 +53,6 @@ class DMRaidMember(DeviceFormat):
     _linuxNative = False                # for clearpart
     _packages = ["dmraid"]              # required packages
     _resizable = False                  # can be resized
-    _maxSize = 0                        # maximum size in MB
-    _minSize = 0                        # minimum size in MB
     _hidden = True                      # hide devices with this formatting?
 
     def __init__(self, *args, **kwargs):
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
index cf54c31..a51ef92 100644
--- a/blivet/formats/fs.py
+++ b/blivet/formats/fs.py
@@ -22,7 +22,7 @@
 #
 
 """ Filesystem classes. """
-import math
+from decimal import Decimal
 import os
 import sys
 import tempfile
@@ -36,6 +36,7 @@ from ..flags import flags
 from parted import fileSystemType
 from ..storage_log import log_method_call
 from .. import arch
+from ..size import Size
 from ..i18n import _, N_
 
 import logging
@@ -46,12 +47,6 @@ try:
 except OSError:
     lost_and_found_context = None
 
-# these are for converting to/from SI for ntfsresize
-mb = 1000 * 1000.0
-mib = 1024 * 1024.0
-gib = 1024 * 1024 * 1024.0
-
-
 fs_configs = {}
 
 kernel_filesystems = []
@@ -159,7 +154,7 @@ class FS(DeviceFormat):
         self.fsprofile = kwargs.get("fsprofile")
 
         # filesystem size does not necessarily equal device size
-        self._size = kwargs.get("size", 0)
+        self._size = kwargs.get("size", Size(bytes=0))
         self._minInstanceSize = None    # min size of this FS instance
         self._mountpoint = None     # the current mountpoint when mounted
 
@@ -330,8 +325,7 @@ class FS(DeviceFormat):
                 for value in values:
                     size *= value
 
-                # report current size as megabytes
-                size = math.floor(size / 1024.0 / 1024.0)
+                size = Size(bytes=size)
             except Exception as e:
                 log.error("failed to obtain size of filesystem on %s: %s"
                           % (self.device, e))
@@ -341,10 +335,10 @@ class FS(DeviceFormat):
     @property
     def currentSize(self):
         """ The filesystem's current actual size. """
-        size = 0
+        size = Size(bytes=0)
         if self.exists:
             size = self._size
-        return float(size)
+        return size
 
     @property
     def free(self):
@@ -411,7 +405,7 @@ class FS(DeviceFormat):
 
     @property
     def resizeArgs(self):
-        argv = [self.device, "%d" % (self.targetSize,)]
+        argv = [self.device, "%d" % (self.targetSize.convertTo("MiB"),)]
         return argv
 
     def doResize(self, *args, **kwargs):
@@ -863,8 +857,8 @@ class Ext2FS(FS):
     _supported = True
     _resizable = True
     _linuxNative = True
-    _maxSize = 8 * 1024 * 1024
-    _minSize = 0
+    _maxSize = Size(en_spec="8 GiB")
+    _minSize = Size(bytes=0)
     _defaultFormatOptions = []
     _defaultMountOptions = ["defaults"]
     _defaultCheckOptions = ["-f", "-p", "-C", "0"]
@@ -953,7 +947,7 @@ class Ext2FS(FS):
                 # to bytes, then megabytes, and finally round up.
                 (text, sep, minSize) = line.partition(": ")
                 size = long(minSize) * blockSize
-                size = math.ceil(size / 1024.0 / 1024.0)
+                size = Size(bytes=size)
                 break
 
             if size is None:
@@ -961,7 +955,8 @@ class Ext2FS(FS):
                             "on %s" % (self.mountType, self.device))
             else:
                 orig_size = size
-                size = min(size * 1.1, size + 500, self.currentSize)
+                log.debug("size=%s, current=%s" % (size, self.currentSize))
+                size = min(size * Decimal('1.1'), size + 500, self.currentSize)
                 if orig_size < size:
                     log.debug("padding min size from %d up to %d" % (orig_size, size))
                 else:
@@ -979,7 +974,7 @@ class Ext2FS(FS):
 
     @property
     def resizeArgs(self):
-        argv = ["-p", self.device, "%dM" % (self.targetSize,)]
+        argv = ["-p", self.device, "%dM" % (self.targetSize.convertTo("MiB"))]
         return argv
 
 register_device_format(Ext2FS)
@@ -996,7 +991,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 = 16 * 1024 * 1024
+    _maxSize = Size(en_spec="16 TiB")
 
     @property
     def needsFSCheck(self):
@@ -1027,7 +1022,7 @@ class FATFS(FS):
                    2: N_("Usage error.")}
     _supported = True
     _formattable = True
-    _maxSize = 1024 * 1024
+    _maxSize = Size(en_spec="1 TiB")
     _packages = [ "dosfstools" ]
     _defaultMountOptions = ["umask=0077", "shortname=winnt"]
     # FIXME this should be fat32 in some cases
@@ -1049,7 +1044,7 @@ class EFIFS(FATFS):
     _mountType = "vfat"
     _modules = ["vfat"]
     _name = N_("EFI System Partition")
-    _minSize = 50
+    _minSize = Size(en_spec="50 MiB")
 
     @property
     def supported(self):
@@ -1069,8 +1064,8 @@ class BTRFS(FS):
     _maxLabelChars = 256
     _supported = True
     _packages = ["btrfs-progs"]
-    _minSize = 256
-    _maxSize = 16 * 1024 * 1024
+    _minSize = Size(en_spec="256 MiB")
+    _maxSize = Size(en_spec="16 TiB")
     # FIXME parted needs to be taught about btrfs so that we can set the
     # partition table type correctly for btrfs partitions
     # partedSystem = fileSystemType["btrfs"]
@@ -1126,7 +1121,7 @@ class BTRFS(FS):
 
     @property
     def resizeArgs(self):
-        argv = ["-r", "%dm" % (self.targetSize,), self.device]
+        argv = ["-r", "%dm" % (self.targetSize.convertTo(en_spec="MiB"),), self.device]
         return argv
 
 register_device_format(BTRFS)
@@ -1169,7 +1164,7 @@ class JFS(FS):
     _defaultFormatOptions = ["-q"]
     _defaultLabelOptions = ["-L"]
     _maxLabelChars = 16
-    _maxSize = 8 * 1024 * 1024
+    _maxSize = Size(en_spec="8 TiB")
     _formattable = True
     _linuxNative = True
     _supported = False
@@ -1202,7 +1197,7 @@ class ReiserFS(FS):
     _defaultFormatOptions = ["-f", "-f"]
     _defaultLabelOptions = ["-l"]
     _maxLabelChars = 16
-    _maxSize = 16 * 1024 * 1024
+    _maxSize = Size(en_spec="16 TiB")
     _formattable = True
     _linuxNative = True
     _supported = False
@@ -1225,7 +1220,7 @@ class ReiserFS(FS):
 
     @property
     def resizeArgs(self):
-        argv = ["-s", "%dM" % (self.targetSize,), self.device]
+        argv = ["-s", "%dM" % (self.targetSize.convertTo(en_spec="MiB"),), self.device]
         return argv
 
 register_device_format(ReiserFS)
@@ -1240,7 +1235,7 @@ class XFS(FS):
     _defaultFormatOptions = ["-f"]
     _defaultLabelOptions = ["-L"]
     _maxLabelChars = 16
-    _maxSize = 16 * 1024 * 1024 * 1024 * 1024
+    _maxSize = Size(en_spec="16 EiB")
     _formattable = True
     _linuxNative = True
     _supported = True
@@ -1293,8 +1288,8 @@ class AppleBootstrapFS(HFS):
     _type = "appleboot"
     _mountType = "hfs"
     _name = N_("Apple Bootstrap")
-    _minSize = 800.00 / 1024.00
-    _maxSize = 1
+    _minSize = Size(en_spec="768 KiB")
+    _maxSize = Size(en_spec="1 MiB")
 
     @property
     def supported(self):
@@ -1313,8 +1308,8 @@ class HFSPlus(FS):
     _packages = ["hfsplus-tools"]
     _formattable = True
     _mountType = "hfsplus"
-    _minSize = 1
-    _maxSize = 2 * 1024 * 1024
+    _minSize = Size(en_spec="1 MiB")
+    _maxSize = Size(en_spec="2 TiB")
     _check = True
     partedSystem = fileSystemType["hfs+"]
 
@@ -1341,8 +1336,8 @@ class NTFS(FS):
     _resizefs = "ntfsresize"
     _fsck = "ntfsresize"
     _resizable = True
-    _minSize = 1
-    _maxSize = 16 * 1024 * 1024
+    _minSize = Size(en_spec="1 MiB")
+    _maxSize = Size(en_spec="16 TiB")
     _defaultMountOptions = ["defaults", "ro"]
     _defaultCheckOptions = ["-c"]
     _packages = ["ntfsprogs"]
@@ -1361,7 +1356,7 @@ class NTFS(FS):
         return False
 
     def _getMinSize(self, info=None):
-        """ Set the minimum size for this filesystem in MiB.
+        """ Set the minimum size for this filesystem.
 
             :keyword info: filesystem info buffer
             :type info: str (output of :attr:`infofsProg`)
@@ -1376,8 +1371,8 @@ class NTFS(FS):
                 if not l.startswith("Minsize"):
                     continue
                 try:
-                    minSize = int(l.split(":")[1].strip())  # MB
-                    minSize *= (mb / mib)                   # MiB
+                    # ntfsresize uses SI unit prefixes
+                    minSize = Size(en_spec="%d mb" % l.split(":")[1].strip())
                 except (IndexError, ValueError) as e:
                     minSize = None
                     log.warning("Unable to parse output for minimum size on %s: %s" %(self.device, e))
@@ -1396,20 +1391,16 @@ class NTFS(FS):
 
     @property
     def minSize(self):
-        """ The minimum filesystem size in megabytes. """
+        """ The minimum filesystem size. """
         return self._minInstanceSize
 
     @property
     def resizeArgs(self):
         # You must supply at least two '-f' options to ntfsresize or
         # the proceed question will be presented to you.
-
-        # FIXME: This -1 is because our partition alignment calculations plus
-        # converting back and forth between MiB and MB means the filesystem is
-        # getting resized to be slightly larger than the partition holding it.
-        # This hack just makes the filesystem fit.
-        targetSize = (mib / mb) * (self.targetSize-1) # convert MiB to MB
-        argv = ["-ff", "-s", "%dM" % (targetSize,), self.device]
+        # ntfsresize uses SI unit prefixes
+        argv = ["-ff", "-s", "%dM" % self.targetSize.convertTo(en_spec="mb"),
+                self.device]
         return argv
 
 
@@ -1546,9 +1537,9 @@ class TmpFS(NoDevFS):
         # and 16EB on 64 bit systems
         bits = arch.bits()
         if bits == 32:
-            self._maxSize = 16 * 1024 * 1024
+            self._maxSize = Size(en_spec="16TiB")
         elif bits == 64:
-            self._maxSize = 16 * 1024 * 1024 * 1024 * 1024
+            self._maxSize = Size(en_spec="16EiB")
         # 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
@@ -1558,18 +1549,17 @@ class TmpFS(NoDevFS):
         # be limited to half of the system RAM
         # (sizes of all tmpfs mounts are independent)
         fsoptions = kwargs.get("mountopts")
-        system_ram = util.total_memory() / 1024  # kB to MB
         self._size_option = ""
         if fsoptions:
             # some mount options were specified, replace the default value
             self._options = fsoptions
         if self._size:
             # absolute size for the tmpfs mount has been specified
-            self._size_option = "size=%dm" % self._size
+            self._size_option = "size=%dm" % self._size.convertTo(en_spec="MiB")
         else:
             # if no size option is specified, the tmpfs mount size will be 50%
             # of system RAM by default
-            self._size = system_ram*0.5
+            self._size = util.total_memory()/2
 
     def create(self, *args, **kwargs):
         """ A filesystem is created automatically once tmpfs is mounted. """
@@ -1624,7 +1614,7 @@ class TmpFS(NoDevFS):
             # self._mountpoint is set to the full changeroot path once mounted,
             # so even with changeroot, statvfs should still work fine.
             st = os.statvfs(self._mountpoint)
-            free_space = st.f_bavail * st.f_frsize/1024/1024  # blocks to MB
+            free_space = Size(bytes=st.f_bavail*st.f_frsize)
         else:
             # Free might be called even if the tmpfs mount has not been
             # mounted yet, in this case just return the size set for the mount.
@@ -1653,7 +1643,7 @@ class TmpFS(NoDevFS):
         # the mount command
 
         # add the remount flag, size and any options
-        remount_options = 'remount,size=%dm' % self.targetSize
+        remount_options = 'remount,size=%dm' % self.targetSize.convertTo(en_spec="MiB")
         # if any mount options are defined, append them
         if self._options:
             remount_options = "%s,%s" % (remount_options, self._options)
@@ -1673,7 +1663,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
+            self._size_option = "size=%dm" % self._size.convertTo(en_spec="MiB")
 
 register_device_format(TmpFS)
 
diff --git a/blivet/formats/lvmpv.py b/blivet/formats/lvmpv.py
index 034825e..a1a06c6 100644
--- a/blivet/formats/lvmpv.py
+++ b/blivet/formats/lvmpv.py
@@ -55,7 +55,7 @@ class LVMPhysicalVolume(DeviceFormat):
             :keyword vgName: the name of the VG this PV belongs to
             :keyword vgUuid: the UUID of the VG this PV belongs to
             :keyword peStart: offset of first physical extent
-            :type peStart: float
+            :type peStart: :class:`~.size.Size`
 
             .. note::
 
@@ -71,7 +71,7 @@ class LVMPhysicalVolume(DeviceFormat):
         self.vgUuid = kwargs.get("vgUuid")
         # liblvm may be able to tell us this at some point, even
         # for not-yet-created devices
-        self.peStart = kwargs.get("peStart", lvm.LVM_PE_START)    # in MB
+        self.peStart = kwargs.get("peStart", lvm.LVM_PE_START)
 
         self.inconsistentVG = False
 
diff --git a/blivet/formats/multipath.py b/blivet/formats/multipath.py
index b7e7076..6d19257 100644
--- a/blivet/formats/multipath.py
+++ b/blivet/formats/multipath.py
@@ -42,8 +42,6 @@ class MultipathMember(DeviceFormat):
     _linuxNative = False                # for clearpart
     _packages = ["device-mapper-multipath"] # required packages
     _resizable = False                  # can be resized
-    _maxSize = 0                        # maximum size in MB
-    _minSize = 0                        # minimum size in MB
     _hidden = True                      # hide devices with this formatting?
 
     def __init__(self, *args, **kwargs):
diff --git a/blivet/formats/prepboot.py b/blivet/formats/prepboot.py
index 605486f..c81f309 100644
--- a/blivet/formats/prepboot.py
+++ b/blivet/formats/prepboot.py
@@ -21,6 +21,7 @@
 #
 
 from ..errors import *
+from ..size import Size
 from .. import platform
 from ..i18n import N_
 from . import DeviceFormat, register_device_format
@@ -37,8 +38,8 @@ class PPCPRePBoot(DeviceFormat):
     partedFlag = PARTITION_PREP
     _formattable = True                 # can be formatted
     _linuxNative = True                 # for clearpart
-    _maxSize = 10                       # maximum size in MB
-    _minSize = 4                        # minimum size in MB
+    _maxSize = Size(en_spec="10 MiB")
+    _minSize = Size(en_spec="4 MiB")
 
     def __init__(self, *args, **kwargs):
         """
diff --git a/blivet/formats/swap.py b/blivet/formats/swap.py
index f0c1fd4..67fd9b2 100644
--- a/blivet/formats/swap.py
+++ b/blivet/formats/swap.py
@@ -26,6 +26,7 @@ from ..errors import *
 from ..util import numeric_type
 from ..devicelibs import swap
 from . import DeviceFormat, register_device_format
+from ..size import Size
 
 import logging
 log = logging.getLogger("blivet")
@@ -43,7 +44,7 @@ class SwapSpace(DeviceFormat):
     _linuxNative = True                # for clearpart
 
     #see rhbz#744129 for details
-    _maxSize = 128 * 1024
+    _maxSize = Size(en_spec="128 GiB")
 
     def __init__(self, *args, **kwargs):
         """
diff --git a/blivet/partitioning.py b/blivet/partitioning.py
index c88c90d..e5da886 100644
--- a/blivet/partitioning.py
+++ b/blivet/partitioning.py
@@ -33,6 +33,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 i18n import _
 
 import logging
@@ -42,12 +43,12 @@ def _getCandidateDisks(storage):
     """ Return a list of disks to be used for autopart.
 
         Disks must be partitioned and have a single free region large enough
-        for a default-sized (500MB) partition. They must also be in
+        for a default-sized (500MiB) partition. They must also be in
         :attr:`StorageDiscoveryConfig.clearPartDisks` if it is non-empty.
 
         :param storage: a Blivet instance
         :type storage: :class:`~.Blivet`
-        :returns: a list of partitioned disks with at least 500MB of free space
+        :returns: a list of partitioned disks with at least 500MiB of free space
         :rtype: list of :class:`~.devices.StorageDevice`
     """
     disks = []
@@ -62,7 +63,7 @@ def _getCandidateDisks(storage):
                 part = part.nextPartition()
                 continue
 
-            if part.getSize(unit="MB") > PartitionDevice.defaultSize:
+            if Size(bytes=part.getLength(unit="B")) > PartitionDevice.defaultSize:
                 disks.append(disk)
                 break
 
@@ -130,13 +131,13 @@ def _schedulePartitions(storage, disks):
     all_free.sort(key=lambda f: f.length, reverse=True)
     if not all_free:
         # this should never happen since we've already filtered the disks
-        # to those with at least 500MB free
+        # to those with at least 500MiB free
         log.error("no free space on disks %s" % ([d.name for d in disks],))
         return
 
-    free = all_free[0].getSize()
+    free = Size(bytes=all_free[0].getLength(unit="B"))
     if len(all_free) > 1:
-        free += all_free[1].getSize()
+        free += int(all_free[1].getLength(unit="B"))
 
     # The boot disk must be set at this point. See if any platform-specific
     # stage1 device we might allocate already exists on the boot disk.
@@ -546,8 +547,8 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
         :type disk: :class:`parted.Disk`
         :param part_type: the type of partition we want to allocate
         :type part_type: one of parted's PARTITION_* constants
-        :param req_size: the requested size of the partition in MB
-        :type req_size: int or float
+        :param req_size: the requested size of the partition in MiB
+        :type req_size: :class:`~.size.Size`
         :keyword start: requested start sector for the partition
         :type start: int
         :keyword boot: whether this will be a bootable partition
@@ -558,15 +559,15 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
         :type grow: bool
 
     """
-    log.debug("getBestFreeSpaceRegion: disk=%s part_type=%d req_size=%dMB "
+    log.debug("getBestFreeSpaceRegion: disk=%s part_type=%d req_size=%s "
               "boot=%s best=%s grow=%s start=%s" %
               (disk.device.path, part_type, req_size, boot, best_free, grow,
                start))
     extended = disk.getExtendedPartition()
 
     for free_geom in disk.getFreeSpaceRegions():
-        log.debug("checking %d-%d (%d MB)" % (free_geom.start, free_geom.end,
-                                              free_geom.getSize()))
+        log.debug("checking %d-%d (%s)" % (free_geom.start, free_geom.end,
+                                           Size(bytes=free_geom.getLength(unit="B"))))
         if start is not None and not free_geom.containsSector(start):
             log.debug("free region does not contain requested start sector")
             continue
@@ -583,17 +584,18 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
             continue
 
         if boot:
-            free_start_mb = sectorsToSize(free_geom.start,
-                                          disk.device.sectorSize)
-            req_end_mb = free_start_mb + req_size
-            if req_end_mb > 2*1024*1024:
-                log.debug("free range position would place boot req above 2TB")
+            max_boot = Size(en_spec="2 TiB")
+            free_start = Size(bytes=(free_geom.start * disk.device.sectorSize))
+            req_end = free_start + req_size
+            if req_end > max_boot:
+                log.debug("free range position would place boot req above %s",
+                            max_boot)
                 continue
 
-        log.debug("current free range is %d-%d (%dMB)" % (free_geom.start,
-                                                          free_geom.end,
-                                                          free_geom.getSize()))
-        free_size = free_geom.getSize()
+        log.debug("current free range is %d-%d (%s)" % (free_geom.start,
+                                                        free_geom.end,
+                                                        Size(bytes=free_geom.getLength(unit="B"))))
+        free_size = Size(bytes=free_geom.getLength(unit="B"))
 
         # For boot partitions, we want the first suitable region we find.
         # For growable or extended partitions, we want the largest possible
@@ -616,28 +618,29 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
     return best_free
 
 def sectorsToSize(sectors, sectorSize):
-    """ Convert length in sectors to size in MB.
+    """ Convert length in sectors to size.
 
         :param sectors: sector count
         :type sectors: int
         :param sectorSize: sector size
-        :type sectorSize: int
+        :type sectorSize: :class:`~.size.Size`
         :returns: the size
-        :rtype: float
+        :rtype: :class:`~.size.Size`
     """
-    return (sectors * sectorSize) / (1024.0 * 1024.0)
+    return Size(bytes=(sectors * sectorSize))
 
 def sizeToSectors(size, sectorSize):
-    """ Convert size in MB to length in sectors.
+    """ Convert size to length in sectors.
 
-        :param size: size in MB
-        :type size: int or float
-        :param sectorSize: sector size
-        :type sectorSize: int
+        :param size: size
+        :type size: :class:`~.size.Size`
+        :param sectorSize: sector size in bytes
+        :type sectorSize: :class:`~.size.Size`
         :returns: sector count
         :rtype: int
     """
-    return (size * 1024.0 * 1024.0) / sectorSize
+    sectors = int(size / sectorSize)
+    return sectors
 
 def removeNewPartitions(disks, partitions):
     """ Remove newly added partitions from disks.
@@ -688,8 +691,8 @@ def addPartition(disklabel, free, part_type, size, start=None, end=None):
         :type free: :class:`parted.Geometry`
         :param part_type: the partition type
         :type part_type: a parted.PARTITION_* constant
-        :param size: size of the new partition in MB
-        :type size: int or float
+        :param size: size of the new partition
+        :type size: :class:`~.size.Size`
         :keyword start: starting sector for the partition
         :type start: int
         :keyword end: ending sector for the partition
@@ -704,10 +707,10 @@ def addPartition(disklabel, free, part_type, size, start=None, end=None):
             alignment unless a start sector is provided.
 
     """
+    sectorSize = Size(bytes=disklabel.partedDevice.sectorSize)
     if start is not None:
         if end is None:
-            end = start + \
-                  sizeToSectors(size, disklabel.partedDevice.sectorSize) - 1
+            end = start + sizeToSectors(size, sectorSize) - 1
     else:
         start = free.start
 
@@ -728,8 +731,7 @@ def addPartition(disklabel, free, part_type, size, start=None, end=None):
             end = free.end
             length = end - start + 1
         else:
-            # size is in MB
-            length = sizeToSectors(size, disklabel.partedDevice.sectorSize)
+            length = sizeToSectors(size, sectorSize)
             end = start + length - 1
 
         if not disklabel.endAlignment.isAligned(free, end):
@@ -877,7 +879,7 @@ def doPartitioning(storage):
     else:
         # Mark all growable requests as no longer growable.
         for partition in storage.partitions:
-            log.debug("fixing size of %s at %.2f" % (partition, partition.size))
+            log.debug("fixing size of %s" % partition)
             partition.req_grow = False
             partition.req_base_size = partition.size
             partition.req_size = partition.size
@@ -900,12 +902,12 @@ def doPartitioning(storage):
             problem = part.checkSize()
             if problem < 0:
                 raise PartitioningError(_("partition is too small for %(format)s formatting "
-                                        "(allowable size is %(minSize)d MB to %(maxSize)d MB)")
+                                        "(allowable size is %(minSize)s to %(maxSize)s)")
                                         % {"format": part.format.name, "minSize": part.format.minSize,
                                             "maxSize": part.format.maxSize})
             elif problem > 0:
                 raise PartitioningError(_("partition is too large for %(format)s formatting "
-                                        "(allowable size is %(minSize)d MB to %(maxSize)d MB)")
+                                        "(allowable size is %(minSize)s to %(maxSize)s)")
                                         % {"format": part.format.name, "minSize": part.format.minSize,
                                             "maxSize": part.format.maxSize})
 
@@ -974,7 +976,7 @@ def allocatePartitions(storage, disks, partitions, freespace):
         boot = _part.req_base_weight > 1000
 
         log.debug("allocating partition: %s ; id: %d ; disks: %s ;\n"
-                  "boot: %s ; primary: %s ; size: %dMB ; grow: %s ; "
+                  "boot: %s ; primary: %s ; size: %s ; grow: %s ; "
                   "max_size: %s ; start: %s ; end: %s" % (_part.name, _part.id,
                                     [d.name for d in req_disks],
                                     boot, _part.req_primary,
@@ -984,11 +986,11 @@ def allocatePartitions(storage, disks, partitions, freespace):
         free = None
         use_disk = None
         part_type = None
-        growth = 0
+        growth = 0  # in sectors
         # loop through disks
         for _disk in req_disks:
             disklabel = disklabels[_disk.path]
-            sectorSize = disklabel.partedDevice.sectorSize
+            sectorSize = Size(bytes=disklabel.partedDevice.sectorSize)
             best = None
             current_free = free
 
@@ -1101,16 +1103,16 @@ def allocatePartitions(storage, disks, partitions, freespace):
                                                temp_parts, freespace)
 
                         # grow all growable requests
-                        disk_growth = 0
-                        disk_sector_size = disklabels[disk_path].partedDevice.sectorSize
+                        disk_growth = 0 # in sectors
+                        disk_sector_size = Size(bytes=disklabels[disk_path].partedDevice.sectorSize)
                         for chunk in chunks:
                             chunk.growRequests()
                             # record the growth for this layout
                             new_growth += chunk.growth
                             disk_growth += chunk.growth
                             for req in chunk.requests:
-                                log.debug("request %d (%s) growth: %d (%dMB) "
-                                          "size: %dMB" %
+                                log.debug("request %d (%s) growth: %d (%s) "
+                                          "size: %s" %
                                           (req.device.id,
                                            req.device.name,
                                            req.growth,
@@ -1118,7 +1120,7 @@ def allocatePartitions(storage, disks, partitions, freespace):
                                                          disk_sector_size),
                                            sectorsToSize(req.growth + req.base,
                                                          disk_sector_size)))
-                        log.debug("disk %s growth: %d (%dMB)" %
+                        log.debug("disk %s growth: %d (%s)" %
                                         (disk_path, disk_growth,
                                          sectorsToSize(disk_growth,
                                                        disk_sector_size)))
@@ -1149,9 +1151,9 @@ def allocatePartitions(storage, disks, partitions, freespace):
                                 % (_disk.name, new_part_type))
                     part_type = new_part_type
                     use_disk = _disk
-                    log.debug("new free: %d-%d / %dMB" % (best.start,
-                                                          best.end,
-                                                          best.getSize()))
+                    log.debug("new free: %d-%d / %s" % (best.start,
+                                                        best.end,
+                                                        Size(bytes=best.getLength(unit="B"))))
                     log.debug("new free allows for %d sectors of growth" %
                                 growth)
                     free = best
@@ -1192,8 +1194,9 @@ def allocatePartitions(storage, disks, partitions, freespace):
 
         partition = addPartition(disklabel, free, part_type, _part.req_size,
                                  _part.req_start_sector, _part.req_end_sector)
-        log.debug("created partition %s of %dMB and added it to %s" %
-                (partition.getDeviceNodeName(), partition.getSize(),
+        log.debug("created partition %s of %s and added it to %s" %
+                (partition.getDeviceNodeName(),
+                 Size(bytes=partition.getLength(unit="B")),
                  disklabel.device))
 
         # this one sets the name
@@ -1254,7 +1257,7 @@ class PartitionRequest(Request):
         super(PartitionRequest, self).__init__(partition)
         self.base = partition.partedPartition.geometry.length   # base sectors
 
-        sector_size = partition.partedPartition.disk.device.sectorSize
+        sector_size = Size(bytes=partition.partedPartition.disk.device.sectorSize)
 
         if partition.req_grow:
             limits = filter(lambda l: l > 0,
@@ -1280,10 +1283,10 @@ class LVRequest(Request):
 
         # Round up to nearest pe. For growable requests this will mean that
         # first growth is to fill the remainder of any unused extent.
-        self.base = lv.vg.align(lv.req_size, roundup=True) / lv.vg.peSize # pe
+        self.base = int(lv.vg.align(lv.req_size, roundup=True) / lv.vg.peSize)
 
         if lv.req_grow:
-            limits = [l / lv.vg.peSize for l in
+            limits = [int(l / lv.vg.peSize) for l in
                         [lv.vg.align(lv.req_max_size),
                          lv.vg.align(lv.format.maxSize)] if l > 0]
 
@@ -1319,7 +1322,7 @@ class Chunk(object):
 
     def __repr__(self):
         s = ("%(type)s instance --\n"
-             "device = %(device)s  length = %(length)d  size = %(size)d\n"
+             "device = %(device)s  length = %(length)d  size = %(size)s\n"
              "remaining = %(rem)d  pool = %(pool)d" %
              {"type": self.__class__.__name__, "device": self.path,
               "length": self.length, "size": self.lengthToSize(self.length),
@@ -1355,7 +1358,7 @@ class Chunk(object):
             :raises: ValueError
             :returns: None
         """
-        log.debug("reclaim: %s %d (%d MB)" % (request, amount, self.lengthToSize(amount)))
+        log.debug("reclaim: %s %d (%s)" % (request, amount, self.lengthToSize(amount)))
         if request.growth < amount:
             log.error("tried to reclaim %d from request with %d of growth"
                         % (amount, request.growth))
@@ -1416,7 +1419,7 @@ class Chunk(object):
             if req.growth > max_growth:
                 # we've grown beyond the maximum. put some back.
                 extra = req.growth - max_growth
-                log.debug("taking back %d (%dMB) from %d (%s)" %
+                log.debug("taking back %d (%s) from %d (%s)" %
                             (extra, self.lengthToSize(extra),
                              req.device.id, req.device.name))
                 self.pool += extra
@@ -1463,9 +1466,9 @@ class Chunk(object):
             last_pool = self.pool    # to keep from getting stuck
             self.base = new_base
             if uniform:
-                growth = last_pool / self.remaining
+                growth = int(last_pool / self.remaining)
 
-            log.debug("%d requests and %d (%dMB) left in chunk" %
+            log.debug("%d requests and %s (%s) left in chunk" %
                         (self.remaining, self.pool, self.lengthToSize(self.pool)))
             for p in self.requests:
                 if p.done or p in self.skip_list:
@@ -1480,13 +1483,13 @@ class Chunk(object):
 
                 p.growth += growth
                 self.pool -= growth
-                log.debug("adding %d (%dMB) to %d (%s)" %
+                log.debug("adding %s (%s) to %d (%s)" %
                             (growth, self.lengthToSize(growth),
                              p.device.id, p.device.name))
 
                 new_base = self.trimOverGrownRequest(p, base=new_base)
-                log.debug("new grow amount for request %d (%s) is %d "
-                          "units, or %dMB" %
+                log.debug("new grow amount for request %d (%s) is %s "
+                          "units, or %s" %
                             (p.device.id, p.device.name, p.growth,
                              self.lengthToSize(p.growth)))
 
@@ -1500,13 +1503,13 @@ class Chunk(object):
                 growth = self.pool
                 p.growth += growth
                 self.pool = 0
-                log.debug("adding %d (%dMB) to %d (%s)" %
+                log.debug("adding %s (%s) to %d (%s)" %
                             (growth, self.lengthToSize(growth),
                              p.device.id, p.device.name))
 
                 self.trimOverGrownRequest(p)
-                log.debug("new grow amount for request %d (%s) is %d "
-                          "units, or %dMB" %
+                log.debug("new grow amount for request %d (%s) is %s "
+                          "units, or %s" %
                             (p.device.id, p.device.name, p.growth,
                              self.lengthToSize(p.growth)))
 
@@ -1533,14 +1536,14 @@ class DiskChunk(Chunk):
 
         """
         self.geometry = geometry            # parted.Geometry
-        self.sectorSize = self.geometry.device.sectorSize
+        self.sectorSize = Size(bytes=self.geometry.device.sectorSize)
         self.path = self.geometry.device.path
         super(DiskChunk, self).__init__(self.geometry.length, requests=requests)
 
     def __repr__(self):
         s = super(DiskChunk, self).__str__()
         s += (" start = %(start)d  end = %(end)d\n"
-              "sectorSize = %(sectorSize)d\n" %
+              "sectorSize = %(sectorSize)s\n" %
               {"start": self.geometry.start, "end": self.geometry.end,
                "sectorSize": self.sectorSize})
         return s
@@ -1612,7 +1615,8 @@ class DiskChunk(Chunk):
 
         # 2TB limit on bootable partitions, regardless of disklabel
         if req.device.req_bootable:
-            limits.append(sizeToSectors(2*1024*1024, self.sectorSize) - req_end)
+            max_boot = sizeToSectors(Size(en_spec="2 TiB"), self.sectorSize)
+            limits.append(max_boot - req_end)
 
         # request-specific maximum (see Request.__init__, above, for details)
         if req.max_growth:
@@ -1643,7 +1647,7 @@ class VGChunk(Chunk):
         """
         self.vg = vg
         self.path = vg.path
-        usable_extents = vg.extents - (vg.reservedSpace / vg.peSize)
+        usable_extents = vg.extents - int(vg.align(vg.reservedSpace, roundup=True) / vg.peSize)
         super(VGChunk, self).__init__(usable_extents, requests=requests)
 
     def addRequest(self, req):
@@ -1659,10 +1663,10 @@ class VGChunk(Chunk):
         super(VGChunk, self).addRequest(req)
 
     def lengthToSize(self, length):
-        return length * self.vg.peSize
+        return self.vg.peSize * length
 
     def sizeToLength(self, size):
-        return size / self.vg.peSize
+        return int(size / self.vg.peSize)
 
     def sortRequests(self):
         # sort the partitions by start sector
@@ -1693,13 +1697,13 @@ class VGChunk(Chunk):
             growth = int(req.device.req_percent * 0.01 * self.length)# truncate
             req.growth += growth
             self.pool -= growth
-            log.debug("adding %d (%dMB) to %d (%s)" %
+            log.debug("adding %d (%s) to %d (%s)" %
                         (growth, self.lengthToSize(growth),
                          req.device.id, req.device.name))
 
             new_base = self.trimOverGrownRequest(req)
             log.debug("new grow amount for request %d (%s) is %d "
-                      "units, or %dMB" %
+                      "units, or %s" %
                         (req.device.id, req.device.name, req.growth,
                          self.lengthToSize(req.growth)))
 
@@ -1771,8 +1775,8 @@ class TotalSizeSet(object):
         """
             :param devices: the set of devices
             :type devices: list of :class:`~.devices.PartitionDevice`
-            :param size: the target combined size in MB
-            :type size: int or float
+            :param size: the target combined size
+            :type size: :class:`~.size.Size`
         """
         self.devices = []
         for device in devices:
@@ -1810,12 +1814,12 @@ class SameSizeSet(object):
         """
             :param devices: the set of devices
             :type devices: list of :class:`~.devices.PartitionDevice`
-            :param size: target size for each device/request in MB
-            :type size: int or float
+            :param size: target size for each device/request
+            :type size: :class:`~.size.Size`
             :keyword grow: whether the devices can be grown
             :type grow: bool
-            :keyword max_size: the maximum size for growable devices in MB
-            :type max_size: int or float
+            :keyword max_size: the maximum size for growable devices
+            :type max_size: :class:`~.size.Size`
         """
         self.devices = []
         for device in devices:
@@ -1955,8 +1959,6 @@ def growPartitions(disks, partitions, free, size_sets=None):
     #
     chunks = []
     for disk in disks:
-        sector_size = disk.format.partedDevice.sectorSize
-
         # list of free space regions on this disk prior to partition allocation
         disk_free = [f for f in free if f.device.path == disk.path]
         if not disk_free:
@@ -2146,7 +2148,7 @@ def growLVM(storage):
             log.debug("vg %s has no free space" % vg.name)
             continue
 
-        log.debug("vg %s: %dMB free ; lvs: %s" % (vg.name, total_free,
+        log.debug("vg %s: %s free ; lvs: %s" % (vg.name, total_free,
                                                   [l.lvname for l in vg.lvs]))
 
         # don't include thin lvs in the vg's growth calculation
diff --git a/blivet/partspec.py b/blivet/partspec.py
index 5ee67c9..04efc70 100644
--- a/blivet/partspec.py
+++ b/blivet/partspec.py
@@ -43,7 +43,7 @@ class PartSpec(object):
                       appleboot, etc.) partitions end up in front of /boot.
                       This value means nothing unless lv and btr are both False.
             requiredSpace -- This value is only taken into account if
-                             lv=True, and specifies the size in MB that the
+                             lv=True, and specifies the size in MiB that the
                              containing VG must be for this PartSpec to even
                              get used.  The VG's size is calculated before any
                              other LVs are created inside it.  If not enough
diff --git a/blivet/platform.py b/blivet/platform.py
index 95f2c48..e673156 100644
--- a/blivet/platform.py
+++ b/blivet/platform.py
@@ -28,6 +28,7 @@ import parted
 from . import arch
 from .flags import flags
 from .partspec import PartSpec
+from .size import Size
 from .i18n import _, N_
 
 class Platform(object):
@@ -44,7 +45,7 @@ class Platform(object):
     _boot_stage1_device_types = []
     _boot_stage1_format_types = []
     _boot_stage1_mountpoints = []
-    _boot_stage1_max_end_mb = None
+    _boot_stage1_max_end = None
     _boot_stage1_raid_levels = []
     _boot_stage1_raid_metadata = []
     _boot_stage1_raid_member_types = []
@@ -85,7 +86,7 @@ class Platform(object):
         d = {"device_types": self._boot_stage1_device_types,
              "format_types": self._boot_stage1_format_types,
              "mountpoints": self._boot_stage1_mountpoints,
-             "max_end_mb": self._boot_stage1_max_end_mb,
+             "max_end": self._boot_stage1_max_end,
              "raid_levels": self._boot_stage1_raid_levels,
              "raid_metadata": self._boot_stage1_raid_metadata,
              "raid_member_types": self._boot_stage1_raid_member_types,
@@ -134,8 +135,8 @@ class Platform(object):
 
     def setDefaultPartitioning(self):
         """Return the default platform-specific partitioning information."""
-        return [PartSpec(mountpoint="/boot",
-                         size=500, weight=self.weight(mountpoint="/boot"))]
+        return [PartSpec(mountpoint="/boot", size=Size(en_spec="500MiB"),
+                         weight=self.weight(mountpoint="/boot"))]
 
     def weight(self, fstype=None, mountpoint=None):
         """ Given an fstype (as a string) or a mountpoint, return an integer
@@ -165,7 +166,7 @@ class X86(Platform):
     def setDefaultPartitioning(self):
         """Return the default platform-specific partitioning information."""
         ret = Platform.setDefaultPartitioning(self)
-        ret.append(PartSpec(fstype="biosboot", size=1,
+        ret.append(PartSpec(fstype="biosboot", size=Size(en_spec="1MiB"),
                             weight=self.weight(fstype="biosboot")))
         return ret
 
@@ -193,8 +194,8 @@ class EFI(Platform):
 
     def setDefaultPartitioning(self):
         ret = Platform.setDefaultPartitioning(self)
-        ret.append(PartSpec(mountpoint="/boot/efi", fstype="efi", size=20,
-                            maxSize=200,
+        ret.append(PartSpec(mountpoint="/boot/efi", fstype="efi",
+                            size=Size(en_spec="20MiB"), maxSize=Size(en_spec="200MiB"),
                             grow=True, weight=self.weight(fstype="efi")))
         return ret
 
@@ -215,8 +216,8 @@ class MacEFI(EFI):
 
     def setDefaultPartitioning(self):
         ret = Platform.setDefaultPartitioning(self)
-        ret.append(PartSpec(mountpoint="/boot/efi", fstype="macefi", size=20,
-                            maxSize=200,
+        ret.append(PartSpec(mountpoint="/boot/efi", fstype="macefi",
+                            size=Size(en_spec="20MiB"), maxSize=Size(en_spec="200MiB"),
                             grow=True, weight=self.weight(mountpoint="/boot/efi")))
         return ret
 
@@ -230,14 +231,14 @@ class PPC(Platform):
 
 class IPSeriesPPC(PPC):
     _boot_stage1_format_types = ["prepboot"]
-    _boot_stage1_max_end_mb = 10
+    _boot_stage1_max_end = Size(en_spec="2 GiB")
     _boot_prep_description = N_("PReP Boot Partition")
     _boot_descriptions = {"partition": _boot_prep_description}
     _disklabel_types = ["msdos"]
 
     def setDefaultPartitioning(self):
         ret = PPC.setDefaultPartitioning(self)
-        ret.append(PartSpec(fstype="prepboot", size=4,
+        ret.append(PartSpec(fstype="prepboot", size=Size(en_spec="4MiB"),
                             weight=self.weight(fstype="prepboot")))
         return ret
 
@@ -259,7 +260,7 @@ class NewWorldPPC(PPC):
 
     def setDefaultPartitioning(self):
         ret = Platform.setDefaultPartitioning(self)
-        ret.append(PartSpec(fstype="appleboot", size=1, maxSize=1,
+        ret.append(PartSpec(fstype="appleboot", size=Size(en_spec="1MiB"),
                             weight=self.weight(fstype="appleboot")))
         return ret
 
@@ -292,7 +293,7 @@ class S390(Platform):
 
     def setDefaultPartitioning(self):
         """Return the default platform-specific partitioning information."""
-        return [PartSpec(mountpoint="/boot", size=500,
+        return [PartSpec(mountpoint="/boot", size=Size(en_spec="500MiB"),
                          weight=self.weight(mountpoint="/boot"), lv=True,
                          singlePV=True)]
 
@@ -337,10 +338,11 @@ class omapARM(ARM):
     def setDefaultPartitioning(self):
         """Return the ARM-OMAP platform-specific partitioning information."""
         ret = [PartSpec(mountpoint="/boot/uboot", fstype="vfat",
-                        size=20, maxSize=200, grow=True,
+                        size=Size(en_spec="20MiB"), maxSize=Size(en_spec="200MiB"),
+                        grow=True,
                         weight=self.weight(fstype="vfat", mountpoint="/boot/uboot"))]
         ret.append(PartSpec(mountpoint="/", fstype="ext4",
-                            size=2000, maxSize=3000,
+                            size=Size(en_spec="2GiB"), maxSize=Size(en_spec="3GiB"),
                             weight=self.weight(mountpoint="/")))
         return ret
 
diff --git a/blivet/size.py b/blivet/size.py
index b98a52c..0173ac6 100644
--- a/blivet/size.py
+++ b/blivet/size.py
@@ -174,6 +174,9 @@ class Size(Decimal):
     def __repr__(self):
         return "Size('%s')" % self
 
+    def __deepcopy__(self, memo):
+        return Size(bytes=self.convertTo(en_spec="b"))
+
     def __add__(self, other, context=None):
         return Size(bytes=Decimal.__add__(self, other, context=context))
 
@@ -192,6 +195,9 @@ class Size(Decimal):
     def __div__(self, other, context=None):
         return Size(bytes=Decimal.__div__(self, other, context=context))
 
+    def __mod__(self, other, context=None):
+        return Size(bytes=Decimal.__mod__(self, other, context=context))
+
     def _trimEnd(self, val):
         """ Internal method to trim trailing zeros. """
         val = re.sub(r'(\.\d*?)0+$', '\\1', val)
@@ -229,7 +235,7 @@ class Size(Decimal):
         else:
             bytes = _bytes
         if spec in bytes:
-            return Decimal(self)
+            return self
 
         if xlate:
             prefixes = [_(p) for p in _prefixes]
diff --git a/blivet/udev.py b/blivet/udev.py
index ebcf92e..a0c92a6 100644
--- a/blivet/udev.py
+++ b/blivet/udev.py
@@ -26,6 +26,7 @@ import re
 
 import util
 from errors import *
+from size import Size
 
 import pyudev
 global_udev = pyudev.Udev()
@@ -397,18 +398,16 @@ def udev_device_get_vg_uuid(info):
 
 def udev_device_get_vg_size(info):
     # lvm's decmial precision is not configurable, so we tell it to use
-    # KB and convert to MB here
-    return float(info['LVM2_VG_SIZE']) / 1024
+    # KB.
+    return Size(en_spec="%s kib" % info['LVM2_VG_SIZE'])
 
 def udev_device_get_vg_free(info):
     # lvm's decmial precision is not configurable, so we tell it to use
-    # KB and convert to MB here
-    return float(info['LVM2_VG_FREE']) / 1024
+    # KB.
+    return Size(en_spec="%s kib" % info['LVM2_VG_FREE'])
 
 def udev_device_get_vg_extent_size(info):
-    # lvm's decmial precision is not configurable, so we tell it to use
-    # KB and convert to MB here
-    return float(info['LVM2_VG_EXTENT_SIZE']) / 1024
+    return Size(en_spec="%s kib" % info['LVM2_VG_EXTENT_SIZE'])
 
 def udev_device_get_vg_extent_count(info):
     return int(info['LVM2_VG_EXTENT_COUNT'])
@@ -420,9 +419,7 @@ def udev_device_get_vg_pv_count(info):
     return int(info['LVM2_PV_COUNT'])
 
 def udev_device_get_pv_pe_start(info):
-    # lvm's decmial precision is not configurable, so we tell it to use
-    # KB and convert to MB here
-    return float(info['LVM2_PE_START']) / 1024
+    return Size(en_spec="%s kib" % info['LVM2_PE_START'])
 
 def udev_device_get_lv_names(info):
     names = info['LVM2_LV_NAME']
@@ -441,15 +438,13 @@ def udev_device_get_lv_uuids(info):
     return uuids
 
 def udev_device_get_lv_sizes(info):
-    # lvm's decmial precision is not configurable, so we tell it to use
-    # KB and convert to MB here
     sizes = info['LVM2_LV_SIZE']
     if not sizes:
         sizes = []
     elif not isinstance(sizes, list):
         sizes = [sizes]
 
-    return [float(s) / 1024 for s in sizes]
+    return [Size(en_spec="%s kib" % s) for s in sizes]
 
 def udev_device_get_lv_attr(info):
     attr = info['LVM2_LV_ATTR']
diff --git a/blivet/util.py b/blivet/util.py
index a9efa34..3227100 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -3,8 +3,10 @@ import shutil
 import selinux
 import subprocess
 import re
+from decimal import Decimal
 
 from udev import udev_settle
+from size import Size
 
 import logging
 log = logging.getLogger("blivet")
@@ -127,19 +129,20 @@ def get_mount_device(mountpoint):
     return mount_device
 
 def total_memory():
-    """ Return the amount of system RAM in kilobytes. """
+    """ Return the amount of system RAM.
+
+        :rtype: :class:`~.size.Size`
+    """
     lines = open("/proc/meminfo").readlines()
     for line in lines:
         if line.startswith("MemTotal:"):
-            mem = long(line.split()[1])
+            mem = Size(en_spec="%s KiB" % line.split()[1])
 
     # 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 MB number divisible by 128. */
-    mem /= 1024
-    mem = (mem / 128 + 1) * 128
-    mem *= 1024
-
+    # every machine has the total RAM MiB number divisible by 128. */
+    bs = Size(en_spec="128MiB")
+    mem = (mem / bs + 1) * bs
     return mem
 
 ##
@@ -312,9 +315,7 @@ def numeric_type(num):
     """
     if num is None:
         num = 0
-    elif not (isinstance(num, int) or \
-              isinstance(num, long) or \
-              isinstance(num, float)):
+    elif not isinstance(num, (int, long, float, Size, Decimal)):
         raise ValueError("value (%s) must be either a number or None" % num)
 
     return num
diff --git a/doc/intro.rst b/doc/intro.rst
index e377597..2f7dc5a 100644
--- a/doc/intro.rst
+++ b/doc/intro.rst
@@ -128,6 +128,7 @@ Scheduling a Series of Actions
 Start out as before::
 
     import blivet
+    from blivet.size import Size
     b = blivet.Blivet()
     b.reset()
     sda3 = b.devicetree.getDeviceByName("sda3")
@@ -136,9 +137,9 @@ Now we're going to wipe the existing formatting from sda3::
 
     b.destroyFormat(sda3)
 
-Now let's assume sda3 is larger than 10GB and resize it to that size::
+Now let's assume sda3 is larger than 10GiB and resize it to that size::
 
-    b.resizeDevice(sda3, 10000) # size is in MB
+    b.resizeDevice(sda3, Size(spec="10 GiB"))
 
 And then let's create a new ext4 filesystem there::
 
@@ -168,18 +169,19 @@ occupy. Blivet offers some powerful means for deciding for you where to place
 the partitions, but it also allows you to specify an exact start and end
 sector on a specific disk if that's how you want to do it. Here's an example
 of letting Blivet handle the details of creating a partition of minimum size
-10GB on either sdb or sdc that is also growable to a maximum size of 20GB::
+10GiB on either sdb or sdc that is also growable to a maximum size of 20GiB::
 
     sdb = b.devicetree.getDeviceByName("sdb")
     sdc = b.devicetree.getDeviceByName("sdc")
-    new_part = b.newPartition(size=10000, grow=True, maxsize=20000,
+    new_part = b.newPartition(size=Size(spec="10GiB"), grow=True,
+                              maxsize=Size(spec="20GiB"),
                               parents=[sdb, sdc])
     b.createDevice(new_part)
     blivet.partitioning.doPartitioning(b)
 
 Now you could see where it ended up::
 
-    print("partition %s of size %dMiB on disk %s" % (new_part.name,
+    print("partition %s of size %s on disk %s" % (new_part.name,
                                                      new_part.size,
                                                      new_part.disk.name))
 
diff --git a/examples/factory.py b/examples/factory.py
index 7e6391c..461920e 100644
--- a/examples/factory.py
+++ b/examples/factory.py
@@ -14,13 +14,14 @@ blivet_log = logging.getLogger("blivet")
 blivet_log.info(sys.argv[0])
 
 import blivet
+from blivet.size import Size
 
 b = blivet.Blivet()   # create an instance of Blivet (don't add system devices)
 
 # create two disk image files on which to create new devices
-disk1_file = create_sparse_file(b, "disk1", 100000)
+disk1_file = create_sparse_file(b, "disk1", Size(en_spec="100GiB"))
 b.config.diskImages["disk1"] = disk1_file
-disk2_file = create_sparse_file(b, "disk2", 100000)
+disk2_file = create_sparse_file(b, "disk2", Size(en_spec="100GiB"))
 b.config.diskImages["disk2"] = disk2_file
 
 b.reset()
@@ -32,14 +33,14 @@ try:
     disk2.format = blivet.formats.getFormat("disklabel", device=disk2.path)
 
     # create an lv named data in a vg named testvg
-    device = b.factoryDevice(blivet.devicefactory.DEVICE_TYPE_LVM, 50000,
-                             disks=[disk1, disk2],
+    device = b.factoryDevice(blivet.devicefactory.DEVICE_TYPE_LVM,
+                             Size(en_spec="50GiB"), disks=[disk1, disk2],
                              fstype="xfs", mountpoint="/data")
     print_devices(b)
 
     # change testvg to have an md RAID1 pv instead of partition pvs
-    device = b.factoryDevice(blivet.devicefactory.DEVICE_TYPE_LVM, 50000,
-                             disks=[disk1, disk2],
+    device = b.factoryDevice(blivet.devicefactory.DEVICE_TYPE_LVM,
+                             Size(en_spec="50GiB"), disks=[disk1, disk2],
                              fstype="xfs", mountpoint="/data",
                              container_raid_level="raid1",
                              device=device)
diff --git a/examples/lvm.py b/examples/lvm.py
index fd0fd25..9fdf10d 100644
--- a/examples/lvm.py
+++ b/examples/lvm.py
@@ -19,7 +19,7 @@ from blivet.size import Size
 b = blivet.Blivet()   # create an instance of Blivet (don't add system devices)
 
 # create a disk image file on which to create new devices
-disk1_file = create_sparse_file(b, "disk1", Size(spec="100GB"))
+disk1_file = create_sparse_file(b, "disk1", Size(en_spec="100GiB"))
 b.config.diskImages["disk1"] = disk1_file
 
 b.reset()
@@ -29,7 +29,7 @@ try:
 
     b.initializeDisk(disk1)
 
-    pv = b.newPartition(size=Size(spec="50GB"), fmt_type="lvmpv")
+    pv = b.newPartition(size=Size(en_spec="50GiB"), fmt_type="lvmpv")
     b.createDevice(pv)
 
     # allocate the partitions (decide where and on which disks they'll reside)
@@ -38,18 +38,18 @@ try:
     vg = b.newVG(parents=[pv])
     b.createDevice(vg)
 
-    # new lv with base size 5GB and unbounded growth and an ext4 filesystem
-    dev = b.newLV(fmt_type="ext4", size=Size(spec="5GB"), grow=True,
+    # new lv with base size 5GiB and unbounded growth and an ext4 filesystem
+    dev = b.newLV(fmt_type="ext4", size=Size(en_spec="5GiB"), grow=True,
                   parents=[vg], name="unbounded")
     b.createDevice(dev)
 
-    # new lv with base size 5GB and growth up to 15GB and an ext4 filesystem
-    dev = b.newLV(fmt_type="ext4", size=Size(spec="5GB"), grow=True,
-                  maxsize=Size(spec="15GB"), parents=[vg], name="bounded")
+    # new lv with base size 5GiB and growth up to 15GiB and an ext4 filesystem
+    dev = b.newLV(fmt_type="ext4", size=Size(en_spec="5GiB"), grow=True,
+                  maxsize=Size(en_spec="15GiB"), parents=[vg], name="bounded")
     b.createDevice(dev)
 
-    # new lv with a fixed size of 2GB formatted as swap space
-    dev = b.newLV(fmt_type="swap", size=Size(spec="2GB"), parents=[vg])
+    # new lv with a fixed size of 2GiB formatted as swap space
+    dev = b.newLV(fmt_type="swap", size=Size(en_spec="2GiB"), parents=[vg])
     b.createDevice(dev)
 
     # allocate the growable lvs
diff --git a/examples/partitioning.py b/examples/partitioning.py
index 07c6a73..b4d5155 100644
--- a/examples/partitioning.py
+++ b/examples/partitioning.py
@@ -14,13 +14,14 @@ blivet_log = logging.getLogger("blivet")
 blivet_log.info(sys.argv[0])
 
 import blivet
+from blivet.size import Size
 
 b = blivet.Blivet()   # create an instance of Blivet (don't add system devices)
 
 # create two disk image files on which to create new devices
-disk1_file = create_sparse_file(b, "disk1", 100000)
+disk1_file = create_sparse_file(b, "disk1", Size(en_spec="100GiB"))
 b.config.diskImages["disk1"] = disk1_file
-disk2_file = create_sparse_file(b, "disk2", 100000)
+disk2_file = create_sparse_file(b, "disk2", Size(en_spec="100GiB"))
 b.config.diskImages["disk2"] = disk2_file
 
 b.reset()
@@ -32,20 +33,21 @@ try:
     b.initializeDisk(disk1)
     b.initializeDisk(disk2)
 
-    # new partition on either disk1 or disk2 with base size 10000 MiB and growth
-    # up to a maximum size of 50000 MiB
-    dev = b.newPartition(size=10000, grow=True, maxsize=50000,
-                         parents=[disk1, disk2])
+    # new partition on either disk1 or disk2 with base size 10GiB and growth
+    # up to a maximum size of 50GiB
+    dev = b.newPartition(size=Size(en_spec="10MiB"), maxsize=Size(en_spec="50GiB"),
+                         grow=True, parents=[disk1, disk2])
     b.createDevice(dev)
 
-    # new partition on disk1 with base size 5000 MiB and unbounded growth and an
+    # new partition on disk1 with base size 5GiB and unbounded growth and an
     # ext4 filesystem
-    dev = b.newPartition(fmt_type="ext4", size=5000, grow=True, parents=[disk1])
+    dev = b.newPartition(fmt_type="ext4", size=Size(en_spec="5GiB"), grow=True,
+                         parents=[disk1])
     b.createDevice(dev)
 
-    # new partition on any suitable disk with a fixed size of 2000 MiB formatted
+    # new partition on any suitable disk with a fixed size of 2GiB formatted
     # as swap space
-    dev = b.newPartition(fmt_type="swap", size=2000)
+    dev = b.newPartition(fmt_type="swap", size=Size(en_spec="2GiB"))
     b.createDevice(dev)
 
     # allocate the partitions (decide where and on which disks they'll reside)
diff --git a/tests/devicefactory_test.py b/tests/devicefactory_test.py
index e5f1c74..60d845e 100644
--- a/tests/devicefactory_test.py
+++ b/tests/devicefactory_test.py
@@ -8,6 +8,7 @@ from blivet import devicefactory
 from blivet import devices
 from blivet.devicelibs import mdraid
 from blivet.devicelibs import raid
+from blivet.size import Size
 
 class MDFactoryTestCase(unittest.TestCase):
     """Note that these tests postdate the code that they test.
@@ -19,11 +20,11 @@ class MDFactoryTestCase(unittest.TestCase):
         self.b = blivet.Blivet()
         self.factory1 = devicefactory.get_device_factory(self.b,
            devicefactory.DEVICE_TYPE_MD,
-           1024)
+           Size(spec="1 GiB"))
 
         self.factory2 = devicefactory.get_device_factory(self.b,
            devicefactory.DEVICE_TYPE_MD,
-           1024,
+           Size(spec="1 GiB"),
            raid_level=0)
 
     def testMDFactory(self):
diff --git a/tests/devicelibs_test/lvm_test.py b/tests/devicelibs_test/lvm_test.py
index 824c33c..d239748 100755
--- a/tests/devicelibs_test/lvm_test.py
+++ b/tests/devicelibs_test/lvm_test.py
@@ -4,20 +4,23 @@ import os
 import unittest
 
 import blivet.devicelibs.lvm as lvm
+from blivet.size import Size
 
 class LVMTestCase(unittest.TestCase):
 
     def testGetPossiblePhysicalExtents(self):
         # pass
-        self.assertEqual(lvm.getPossiblePhysicalExtents(4),
-                         filter(lambda pe: pe > 4, map(lambda power: 2**power, xrange(3, 25))))
-        self.assertEqual(lvm.getPossiblePhysicalExtents(100000),
-                         filter(lambda pe: pe > 100000, map(lambda power: 2**power, xrange(3, 25))))
+        self.assertEqual(lvm.getPossiblePhysicalExtents(),
+                         map(lambda power: Size(spec="%d KiB" % 2**power),
+                             xrange(0, 25)))
 
     def testClampSize(self):
         # pass
-        self.assertEqual(lvm.clampSize(10, 4), 8L)
-        self.assertEqual(lvm.clampSize(10, 4, True), 12L)
+        self.assertEqual(lvm.clampSize(Size(spec="10 MiB"), Size(spec="4 MiB")),
+                         Size(spec="8 MiB"))
+        self.assertEqual(lvm.clampSize(Size(spec="10 MiB"), Size(spec="4 MiB"),
+ True),
+                         Size(spec="12 MiB"))
 
     #def testVGUsedSpace(self):
         # TODO
diff --git a/tests/devicelibs_test/mdraid_test.py b/tests/devicelibs_test/mdraid_test.py
index 85fe92f..f7ce2f3 100755
--- a/tests/devicelibs_test/mdraid_test.py
+++ b/tests/devicelibs_test/mdraid_test.py
@@ -6,6 +6,7 @@ import time
 
 import blivet.devicelibs.mdraid as mdraid
 import blivet.errors as errors
+from blivet.size import Size
 
 class MDRaidTestCase(unittest.TestCase):
 
@@ -25,17 +26,26 @@ class MDRaidTestCase(unittest.TestCase):
         ##
         ## get_raid_superblock_size
         ##
-        self.assertEqual(mdraid.get_raid_superblock_size(256 * 1024), 128)
-        self.assertEqual(mdraid.get_raid_superblock_size(128 * 1024), 128)
-        self.assertEqual(mdraid.get_raid_superblock_size(64 * 1024), 64)
-        self.assertEqual(mdraid.get_raid_superblock_size(63 * 1024), 32)
-        self.assertEqual(mdraid.get_raid_superblock_size(10 * 1024), 8)
-        self.assertEqual(mdraid.get_raid_superblock_size(1024), 1)
-        self.assertEqual(mdraid.get_raid_superblock_size(1023), 0)
-        self.assertEqual(mdraid.get_raid_superblock_size(512), 0)
-
-        self.assertEqual(mdraid.get_raid_superblock_size(257, "version"),
-           mdraid.MD_SUPERBLOCK_SIZE)
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="256 GiB")),
+                         Size(spec="128 MiB"))
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="128 GiB")),
+                         Size(spec="128 MiB"))
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="64 GiB")),
+                         Size(spec="64 MiB"))
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="63 GiB")),
+                         Size(spec="32 MiB"))
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="10 GiB")),
+                         Size(spec="8 MiB"))
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="1 GiB")),
+                         Size(spec="1 MiB"))
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="1023 MiB")),
+                         Size(spec="1 MiB"))
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="512 MiB")),
+                         Size(spec="1 MiB"))
+
+        self.assertEqual(mdraid.get_raid_superblock_size(Size(spec="257 MiB"),
+                                                         version="version"),
+                         mdraid.MD_SUPERBLOCK_SIZE)
 
 
 class MDRaidAsRootTestCase(baseclass.DevicelibsTestCase):
diff --git a/tests/devices_test.py b/tests/devices_test.py
index 8507e81..a81ccf5 100644
--- a/tests/devices_test.py
+++ b/tests/devices_test.py
@@ -17,6 +17,7 @@ from blivet.devices import OpticalDevice
 from blivet.devices import StorageDevice
 from blivet.devices import mdraid
 from blivet.devicelibs import btrfs
+from blivet.size import Size
 
 class DeviceStateTestCase(unittest.TestCase):
     """A class which implements a simple method of checking the state
@@ -60,7 +61,7 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
     def setUp(self):
         self._state_functions = {
            "createBitmap" : lambda x,m: self.assertTrue(x, m),
-           "currentSize" : lambda x, m: self.assertEqual(x, 0, m),
+           "currentSize" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "description" : self.assertIsNotNone,
            "devices" : lambda x, m: self.assertEqual(x, [], m),
            "exists" : self.assertFalse,
@@ -70,22 +71,22 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            "isDisk" : self.assertFalse,
            "level" : self.assertIsNone,
            "major" : lambda x, m: self.assertEqual(x, 0, m),
-           "maxSize" : lambda x, m: self.assertEqual(x, 0, m),
+           "maxSize" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "mediaPresent" : self.assertFalse,
            "metadataVersion" : lambda x, m: self.assertEqual(x, "default", m),
            "minor" : lambda x, m: self.assertEqual(x, 0, m),
            "parents" : lambda x, m: self.assertEqual(x, [], m),
            "path" : lambda x, m: self.assertRegexpMatches(x, "^/dev", m),
            "partitionable" : self.assertFalse,
-           "rawArraySize" : lambda x, m: self.assertEqual(x, 0, m),
+           "rawArraySize" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "resizable" : self.assertFalse,
-           "size" : lambda x, m: self.assertEqual(x, 0, m),
+           "size" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "smallestMember" : lambda x, m: self.assertIsNone(x, m),
            "spares" : lambda x, m: self.assertEqual(x, 0, m),
            "status" : self.assertFalse,
-           "superBlockSize" : lambda x, m: self.assertEqual(x, 0, m),
+           "superBlockSize" : lambda x, m: self.assertEqual(x, Size(spec="1 MiB"), m),
            "sysfsPath" : lambda x, m: self.assertEqual(x, "", m),
-           "targetSize" : lambda x, m: self.assertEqual(x, 0, m),
+           "targetSize" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "uuid" : self.assertIsNone,
            "memberDevices" : lambda x, m: self.assertEqual(x, 0, m),
            "totalDevices" : lambda x, m: self.assertEqual(x, 0, m),
@@ -112,7 +113,7 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
         self.dev10 = MDRaidArrayDevice(
            "dev10",
            level="raid0",
-           size=32)
+           size=Size(spec="32 MiB"))
 
         self.dev11 = MDRaidArrayDevice(
            "dev11",
@@ -121,7 +122,7 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            parents=[
               MDRaidArrayDevice("parent", level="container"),
               MDRaidArrayDevice("other", level="raid0")],
-           size=32,
+           size=Size(spec="32 MiB"),
            totalDevices=2)
 
         self.dev12 = MDRaidArrayDevice(
@@ -130,9 +131,9 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            memberDevices=2,
            parents=[
               Mock(**{"type": "mdcontainer",
-                      "size": 4}),
-              Mock(**{"size": 2})],
-           size=32,
+                      "size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")})],
+           size=Size(spec="32 MiB"),
            totalDevices=2)
 
         self.dev13 = MDRaidArrayDevice(
@@ -140,9 +141,9 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            level=0,
            memberDevices=3,
            parents=[
-              Mock(**{"size": 4}),
-              Mock(**{"size": 2})],
-           size=32,
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")})],
+           size=Size(spec="32 MiB"),
            totalDevices=3)
 
         self.dev14 = MDRaidArrayDevice(
@@ -150,9 +151,9 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            level=4,
            memberDevices=3,
            parents=[
-              Mock(**{"size": 4}),
-              Mock(**{"size": 2}),
-              Mock(**{"size": 2})],
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")})],
            totalDevices=3)
 
         self.dev15 = MDRaidArrayDevice(
@@ -160,9 +161,9 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            level=5,
            memberDevices=3,
            parents=[
-              Mock(**{"size": 4}),
-              Mock(**{"size": 2}),
-              Mock(**{"size": 2})],
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")})],
            totalDevices=3)
 
         self.dev16 = MDRaidArrayDevice(
@@ -170,10 +171,10 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            level=6,
            memberDevices=4,
            parents=[
-              Mock(**{"size": 4}),
-              Mock(**{"size": 4}),
-              Mock(**{"size": 2}),
-              Mock(**{"size": 2})],
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")})],
            totalDevices=4)
 
         self.dev17 = MDRaidArrayDevice(
@@ -181,10 +182,10 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            level=10,
            memberDevices=4,
            parents=[
-              Mock(**{"size": 4}),
-              Mock(**{"size": 4}),
-              Mock(**{"size": 2}),
-              Mock(**{"size": 2})],
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")})],
            totalDevices=4)
 
         self.dev18 = MDRaidArrayDevice(
@@ -192,10 +193,10 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
            level=10,
            memberDevices=4,
            parents=[
-              Mock(**{"size": 4}),
-              Mock(**{"size": 4}),
-              Mock(**{"size": 2}),
-              Mock(**{"size": 2})],
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="4 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")}),
+              Mock(**{"size": Size(spec="2 MiB")})],
            totalDevices=5)
 
 
@@ -256,7 +257,7 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
         self.stateCheck(self.dev10,
                         createBitmap=self.assertFalse,
                         level=lambda x, m: self.assertEqual(x.number, 0, m),
-                        targetSize=lambda x, m: self.assertEqual(x, 32, m))
+                        targetSize=lambda x, m: self.assertEqual(x, Size(spec="32 MiB"), m))
 
         self.stateCheck(self.dev11,
                         devices=lambda x, m: self.assertEqual(len(x), 2, m),
@@ -267,7 +268,7 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
                         partitionable=self.assertTrue,
                         smallestMember=self.assertIsNotNone,
-                        targetSize=lambda x, m: self.assertEqual(x, 32, m),
+                        targetSize=lambda x, m: self.assertEqual(x, Size(spec="32 MiB"), m),
                         totalDevices=lambda x, m: self.assertEqual(x, 2, m),
                         type=lambda x, m: self.assertEqual(x, "mdbiosraidarray", m))
 
@@ -282,9 +283,9 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         memberDevices=lambda x, m: self.assertEqual(x, 2, m),
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
                         partitionable=self.assertTrue,
-                        rawArraySize=lambda x, m: self.assertEqual(x, 2, m),
+                        rawArraySize=lambda x, m: self.assertEqual(x, Size(spec="2 MiB"), m),
                         smallestMember=self.assertIsNotNone,
-                        targetSize=lambda x, m: self.assertEqual(x, 32, m),
+                        targetSize=lambda x, m: self.assertEqual(x, Size(spec="32 MiB"), m),
                         totalDevices=lambda x, m: self.assertEqual(x, 2, m),
                         type = lambda x, m: self.assertEqual(x, "mdbiosraidarray", m))
 
@@ -294,10 +295,10 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         level=lambda x, m: self.assertEqual(x.number, 0, m),
                         memberDevices=lambda x, m: self.assertEqual(x, 3, m),
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
-                        rawArraySize=lambda x, m: self.assertEqual(x, 6, m),
-                        size=lambda x, m: self.assertEqual(x, 6, m),
+                        rawArraySize=lambda x, m: self.assertEqual(x, Size(spec="6 MiB"), m),
+                        size=lambda x, m: self.assertEqual(x, Size(spec="3 MiB"), m),
                         smallestMember=self.assertIsNotNone,
-                        targetSize=lambda x, m: self.assertEqual(x, 32, m),
+                        targetSize=lambda x, m: self.assertEqual(x, Size(spec="32 MiB"), m),
                         totalDevices=lambda x, m: self.assertEqual(x, 3, m))
 
         self.stateCheck(self.dev14,
@@ -305,8 +306,8 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         level=lambda x, m: self.assertEqual(x.number, 4, m),
                         memberDevices=lambda x, m: self.assertEqual(x, 3, m),
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
-                        rawArraySize=lambda x, m: self.assertEqual(x, 4, m),
-                        size=lambda x, m: self.assertEqual(x, 4, m),
+                        rawArraySize=lambda x, m: self.assertEqual(x, Size(spec="4 MiB"), m),
+                        size=lambda x, m: self.assertEqual(x, Size(spec="2 MiB"), m),
                         smallestMember=self.assertIsNotNone,
                         totalDevices=lambda x, m: self.assertEqual(x, 3, m))
 
@@ -315,8 +316,8 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         level=lambda x, m: self.assertEqual(x.number, 5, m),
                         memberDevices=lambda x, m: self.assertEqual(x, 3, m),
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
-                        rawArraySize=lambda x, m: self.assertEqual(x, 4, m),
-                        size=lambda x, m: self.assertEqual(x, 4, m),
+                        rawArraySize=lambda x, m: self.assertEqual(x, Size(spec="4 MiB"), m),
+                        size=lambda x, m: self.assertEqual(x, Size(spec="2 MiB"), m),
                         smallestMember=self.assertIsNotNone,
                         totalDevices=lambda x, m: self.assertEqual(x, 3, m))
 
@@ -325,8 +326,8 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         level=lambda x, m: self.assertEqual(x.number, 6, m),
                         memberDevices=lambda x, m: self.assertEqual(x, 4, m),
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
-                        rawArraySize=lambda x, m: self.assertEqual(x, 4, m),
-                        size=lambda x, m: self.assertEqual(x, 4, m),
+                        rawArraySize=lambda x, m: self.assertEqual(x, Size(spec="4 MiB"), m),
+                        size=lambda x, m: self.assertEqual(x, Size(spec="2 MiB"), m),
                         smallestMember=self.assertIsNotNone,
                         totalDevices=lambda x, m: self.assertEqual(x, 4, m))
 
@@ -335,8 +336,8 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         level=lambda x, m: self.assertEqual(x.number, 10, m),
                         memberDevices=lambda x, m: self.assertEqual(x, 4, m),
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
-                        rawArraySize=lambda x, m: self.assertEqual(x, 4, m),
-                        size=lambda x, m: self.assertEqual(x, 4, m),
+                        rawArraySize=lambda x, m: self.assertEqual(x, Size(spec="4 MiB"), m),
+                        size=lambda x, m: self.assertEqual(x, Size(spec="2 MiB"), m),
                         smallestMember=self.assertIsNotNone,
                         totalDevices=lambda x, m: self.assertEqual(x, 4, m))
 
@@ -345,8 +346,8 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase):
                         level=lambda x, m: self.assertEqual(x.number, 10, m),
                         memberDevices=lambda x, m: self.assertEqual(x, 4, m),
                         parents=lambda x, m: self.assertNotEqual(x, [], m),
-                        rawArraySize=lambda x, m: self.assertEqual(x, 4, m),
-                        size=lambda x, m: self.assertEqual(x, 4, m),
+                        rawArraySize=lambda x, m: self.assertEqual(x, Size(spec="4 MiB"), m),
+                        size=lambda x, m: self.assertEqual(x, Size(spec="2 MiB"), m),
                         smallestMember=self.assertIsNotNone,
                         spares=lambda x, m: self.assertEqual(x, 1, m),
                         totalDevices=lambda x, m: self.assertEqual(x, 5, m))
@@ -406,24 +407,24 @@ class BTRFSDeviceTestCase(DeviceStateTestCase):
 
     def setUp(self):
         self._state_functions = {
-           "currentSize" : lambda x, m: self.assertEqual(x, 0, m),
+           "currentSize" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "exists" : self.assertFalse,
            "format" : self.assertIsNotNone,
            "formatArgs" : lambda x, m: self.assertEqual(x, [], m),
            "fstabSpec" : self.assertIsNotNone,
            "isDisk" : self.assertFalse,
            "major" : lambda x, m: self.assertEqual(x, 0, m),
-           "maxSize" : lambda x, m: self.assertEqual(x, 0, m),
+           "maxSize" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "mediaPresent" : self.assertTrue,
            "minor" : lambda x, m: self.assertEqual(x, 0, m),
            "parents" : lambda x, m: self.assertEqual(x, [], m),
            "partitionable" : self.assertFalse,
            "path" : lambda x, m: self.assertRegexpMatches(x, "^/dev", m),
            "resizable" : lambda x, m: self.assertFalse,
-           "size" : lambda x, m: self.assertEqual(x, 0, m),
+           "size" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "status" : self.assertFalse,
            "sysfsPath" : lambda x, m: self.assertEqual(x, "", m),
-           "targetSize" : lambda x, m: self.assertEqual(x, 0, m),
+           "targetSize" : lambda x, m: self.assertEqual(x, Size(bytes=0), m),
            "type" : lambda x, m: self.assertEqual(x, "btrfs", m),
            "uuid" : self.assertIsNone,
            "vol_id" : lambda x, m: self.assertEqual(x, btrfs.MAIN_VOLUME_ID, m)}
@@ -436,7 +437,7 @@ class BTRFSDeviceTestCase(DeviceStateTestCase):
 
         dev = StorageDevice("deva",
            format=blivet.formats.getFormat("btrfs"),
-           size=32)
+           size=Size(spec="32 MiB"))
         self.dev3 = BTRFSVolumeDevice("dev3",
            parents=[dev])
 
@@ -451,10 +452,10 @@ class BTRFSDeviceTestCase(DeviceStateTestCase):
            type=lambda x, m: self.assertEqual(x, "btrfs volume", m))
 
         self.stateCheck(self.dev3,
-           currentSize=lambda x, m: self.assertEqual(x, 32, m),
-           maxSize=lambda x, m: self.assertEqual(x, 32, m),
+           currentSize=lambda x, m: self.assertEqual(x, Size(spec="32 MiB"), m),
+           maxSize=lambda x, m: self.assertEqual(x, Size(spec="32 MiB"), m),
            parents=lambda x, m: self.assertEqual(len(x), 1, m),
-           size=lambda x, m: self.assertEqual(x, 32, m),
+           size=lambda x, m: self.assertEqual(x, Size(spec="32 MiB"), m),
            type=lambda x, m: self.assertEqual(x, "btrfs volume", m))
 
         self.assertRaisesRegexp(ValueError,
diff --git a/tests/size_test.py b/tests/size_test.py
index 5680b43..1e8845d 100644
--- a/tests/size_test.py
+++ b/tests/size_test.py
@@ -71,10 +71,10 @@ class SizeTestCase(unittest.TestCase):
 
     def testHumanReadable(self):
         s = Size(bytes=58929971L)
-        self.assertEquals(s.humanReadable(), "58.92 MB")
+        self.assertEquals(s.humanReadable(), "56.19 MiB")
 
         s = Size(bytes=478360371L)
-        self.assertEquals(s.humanReadable(), "478.36 MB")
+        self.assertEquals(s.humanReadable(), "456.19 MiB")
 
     def testNegative(self):
         s = Size(spec="-500MiB")
diff --git a/tests/storagetestcase.py b/tests/storagetestcase.py
index 0c09ebf..6d8cdbd 100644
--- a/tests/storagetestcase.py
+++ b/tests/storagetestcase.py
@@ -95,6 +95,7 @@ class StorageTestCase(unittest.TestCase):
             # set up mock parted.Device w/ correct size
             device._partedDevice = Mock()
             device._partedDevice.getSize = Mock(return_value=float(device.size))
+            device._partedDevice.getLength = Mock(return_value=float(device.size))
             device._partedDevice.sectorSize = 512
 
         if isinstance(device, blivet.devices.PartitionDevice):
@@ -112,6 +113,7 @@ class StorageTestCase(unittest.TestCase):
             partedPartition.path = device.path
             partedPartition.getDeviceNodeName = Mock(return_value=device.name)
             partedPartition.getSize = Mock(return_value=float(device.size))
+            partedPartition.getLength = Mock(return_value=float(device.size))
             device._partedPartition = partedPartition
 
         device.exists = exists
-- 
1.8.1.4



More information about the anaconda-patches mailing list