Beispiel #1
0
    def testResize(self):
        an_fs = self._fs_class()
        if not an_fs.formattable:
            self.skipTest("can not create filesystem %s" % an_fs.name)
        an_fs.device = self.loopDevices[0]
        self.assertIsNone(an_fs.create())
        an_fs.updateSizeInfo()

        self._test_sizes(an_fs)
        # CHECKME: target size is still 0 after updatedSizeInfo is called.
        self.assertEqual(an_fs.size, Size(0) if an_fs.resizable else an_fs._size)

        if not can_resize(an_fs):
            self.assertFalse(an_fs.resizable)
            # Not resizable, so can not do resizing actions.
            with self.assertRaises(FSError):
                an_fs.targetSize = Size("64 MiB")
            with self.assertRaises(FSError):
                an_fs.doResize()
        else:
            self.assertTrue(an_fs.resizable)
            # Try a reasonable target size
            TARGET_SIZE = Size("64 MiB")
            an_fs.targetSize = TARGET_SIZE
            self.assertEqual(an_fs.targetSize, TARGET_SIZE)
            self.assertNotEqual(an_fs._size, TARGET_SIZE)
            self.assertIsNone(an_fs.doResize())
            ACTUAL_SIZE = TARGET_SIZE.roundToNearest(an_fs._resize.unit, rounding=ROUND_DOWN)
            self.assertEqual(an_fs.size, ACTUAL_SIZE)
            self.assertEqual(an_fs._size, ACTUAL_SIZE)
            self._test_sizes(an_fs)

        # and no errors should occur when checking
        self.assertIsNone(an_fs.doCheck())
Beispiel #2
0
    def testShrink(self):
        an_fs = self._fs_class()
        if not can_resize(an_fs):
            self.skipTest("Not checking resize for this test category.")
        if not an_fs.formattable:
            self.skipTest("can not create filesystem %s" % an_fs.name)

        an_fs.device = self.loopDevices[0]
        self.assertIsNone(an_fs.create())
        an_fs.updateSizeInfo()

        TARGET_SIZE = Size("64 MiB")
        an_fs.targetSize = TARGET_SIZE
        self.assertIsNone(an_fs.doResize())

        TARGET_SIZE = TARGET_SIZE / 2
        self.assertTrue(TARGET_SIZE > an_fs.minSize)
        an_fs.targetSize = TARGET_SIZE
        self.assertEqual(an_fs.targetSize, TARGET_SIZE)
        self.assertNotEqual(an_fs._size, TARGET_SIZE)
        # FIXME:
        # doCheck() in updateSizeInfo() in doResize() does not complete tidily
        # here, so resizable becomes False and self.targetSize can not be
        # assigned to. This alerts us to the fact that now min size
        # and size are both incorrect values.
        if isinstance(an_fs, fs.NTFS):
            return
        self.assertIsNone(an_fs.doResize())
        ACTUAL_SIZE = TARGET_SIZE.roundToNearest(an_fs._resize.unit, rounding=ROUND_DOWN)
        self.assertEqual(an_fs._size, ACTUAL_SIZE)
        self._test_sizes(an_fs)
Beispiel #3
0
    def testExceptions(self):
        zero = Size(0)
        self.assertEqual(zero, 0.0)

        s = Size(500)
        self.assertRaises(SizePlacesError, s.humanReadable, places=-1)

        self.assertEqual(s.humanReadable(places=0), "500 B")
Beispiel #4
0
    def testHumanReadableTranslation(self):
        s = Size("56.19 MiB")
        size_str = s.humanReadable()
        for lang in self.TEST_LANGS:

            os.environ['LANG'] = lang
            locale.setlocale(locale.LC_ALL, '')
            self.assertTrue(s.humanReadable().endswith("%s%s" % (_("Mi"), _("B"))))
            self.assertEqual(s.humanReadable(xlate=False), size_str)
Beispiel #5
0
    def testExceptions(self):
        zero = Size(0)
        self.assertEqual(zero, Size("0.0"))

        s = Size(500)
        with self.assertRaises(SizePlacesError):
            s.humanReadable(max_places=-1)

        self.assertEqual(s.humanReadable(max_places=0), "500 B")
Beispiel #6
0
    def test_exceptions(self):
        zero = Size(0)
        self.assertEqual(zero, Size("0.0"))

        s = Size(500)
        with self.assertRaises(ValueError):
            s.human_readable(max_places="2")

        self.assertEqual(s.human_readable(max_places=0), "500 B")
Beispiel #7
0
    def testExceptions(self):
        self.assertRaises(SizeParamsError, Size)
        self.assertRaises(SizeParamsError, Size, bytes=500, spec="45GB")

        zero = Size(bytes=0)
        self.assertEqual(zero, 0.0)

        s = Size(bytes=500)
        self.assertRaises(SizePlacesError, s.humanReadable, places=-1)

        self.assertEqual(s.humanReadable(places=0), "500 B")
Beispiel #8
0
    def testMinValue(self):
        s = Size("9 MiB")
        self.assertEqual(s.humanReadable(), "9 MiB")
        self.assertEqual(s.humanReadable(min_value=10), "9216 KiB")

        s = Size("0.5 GiB")
        self.assertEqual(s.humanReadable(max_places=2, min_value=1), "512 MiB")
        self.assertEqual(s.humanReadable(max_places=2, min_value=Decimal("0.1")), "0.5 GiB")
        self.assertEqual(s.humanReadable(max_places=2, min_value=Decimal(1)), "512 MiB")
Beispiel #9
0
    def testConvertToWithSize(self):
        s = Size(1835008)
        self.assertEqual(s.convertTo(Size(1)), s.convertTo(B))
        self.assertEqual(s.convertTo(Size(1024)), s.convertTo(KiB))
        self.assertEqual(Size(512).convertTo(Size(1024)), Decimal("0.5"))
        self.assertEqual(Size(1024).convertTo(Size(512)), Decimal(2))

        with self.assertRaises(ValueError):
            s.convertTo(Size(0))
Beispiel #10
0
    def _prefixTestHelper(self, numunits, unit):
        """ Test that units and prefix or abbreviation agree.

            :param int numunits: this value times factor yields number of bytes
            :param unit: a unit specifier
        """
        c = numunits * unit.factor

        s = Size(c)
        self.assertEqual(s, Size(c))

        u = size._makeSpec(unit.prefix, size._BYTES_WORDS[0], False)
        s = Size("%ld %s" % (numunits, u))
        self.assertEqual(s, c)
        self.assertEqual(s.convertTo(unit), numunits)

        u = size._makeSpec(unit.abbr, size._BYTES_SYMBOL, False)
        s = Size("%ld %s" % (numunits, u))
        self.assertEqual(s, c)
        self.assertEqual(s.convertTo(unit), numunits)
Beispiel #11
0
def size_from_input(input_str):
    """Get size from user's input"""

    if not input_str:
        # Nothing to parse
        return None

    # if no unit was specified, default to MiB. Assume that a string
    # ending with anything other than a digit has a unit suffix
    if re.search(r'[\d.%s]$' % locale.nl_langinfo(locale.RADIXCHAR), input_str):
        input_str += "MiB"

    try:
        size = Size(spec=input_str)
    except (SizeParamsError, ValueError):
        return None
    else:
        # Minimium size for ui-created partitions is 1MiB.
        if size.convertTo(spec="MiB") < 1:
            size = Size(spec="1 MiB")

    return size
Beispiel #12
0
    def _prefixTestHelper(self, numbytes, factor, prefix, abbr):
        c = numbytes * factor

        s = Size(c)
        self.assertEquals(s, c)

        if prefix:
            u = "%sbytes" % prefix
            s = Size("%ld %s" % (numbytes, u))
            self.assertEquals(s, c)
            self.assertEquals(s.convertTo(spec=u), numbytes)

        if abbr:
            u = "%sb" % abbr
            s = Size("%ld %s" % (numbytes, u))
            self.assertEquals(s, c)
            self.assertEquals(s.convertTo(spec=u), numbytes)

        if not prefix and not abbr:
            s = Size("%ld" % numbytes)
            self.assertEquals(s, c)
            self.assertEquals(s.convertTo(), numbytes)
Beispiel #13
0
 def testConvertToPrecision(self):
     s = Size(1835008)
     self.assertEqual(s.convertTo(None), 1835008)
     self.assertEqual(s.convertTo(B), 1835008)
     self.assertEqual(s.convertTo(KiB), 1792)
     self.assertEqual(s.convertTo(MiB), Decimal("1.75"))
Beispiel #14
0
 def test_segative(self):
     s = Size("-500MiB")
     self.assertEqual(s.human_readable(), "-500 MiB")
     self.assertEqual(s.convert_to(B), -524288000)
Beispiel #15
0
    def testHumanReadableFractionalQuantities(self):
        s = Size(0xfffffffffffff)
        self.assertEqual(s.humanReadable(max_places=2), "4 PiB")
        s = Size(0xfffff)
        self.assertEqual(s.humanReadable(max_places=2, strip=False), "1024.00 KiB")
        s = Size(0xffff)
        # value is not exactly 64 KiB, but w/ 2 places, value is 64.00 KiB
        # so the trailing 0s are stripped.
        self.assertEqual(s.humanReadable(max_places=2), "64 KiB")
        # since all significant digits are shown, there are no trailing 0s.
        self.assertEqual(s.humanReadable(max_places=None), "63.9990234375 KiB")

        # deviation is less than 1/2 of 1% of 1024
        s = Size(16384 - (1024/100//2))
        self.assertEqual(s.humanReadable(max_places=2), "16 KiB")
        # deviation is greater than 1/2 of 1% of 1024
        s = Size(16384 - ((1024/100//2) + 1))
        self.assertEqual(s.humanReadable(max_places=2), "15.99 KiB")

        s = Size(0x10000000000000)
        self.assertEqual(s.humanReadable(max_places=2), "4 PiB")
Beispiel #16
0
 def start(self, total_files, total_size, total_drpms=0):  # pylint: disable=arguments-differ
     self.total_files = total_files
     self.total_size = Size(total_size)
Beispiel #17
0
 def test_convert_to_precision(self):
     s = Size(1835008)
     self.assertEqual(s.convert_to(None), 1835008)
     self.assertEqual(s.convert_to(B), 1835008)
     self.assertEqual(s.convert_to(KiB), 1792)
     self.assertEqual(s.convert_to(MiB), Decimal("1.75"))
Beispiel #18
0
class ExtendedPartitionTestCase(ImageBackedTestCase):

    disks = {"disk1": Size("2 GiB")}
    initialize_disks = False

    def _set_up_storage(self):
        # Don't rely on the default being an msdos disklabel since the test
        # could be running on an EFI system.
        for name in self.disks:
            disk = self.blivet.devicetree.get_device_by_name(name)
            fmt = get_format("disklabel", label_type="msdos", device=disk.path)
            self.blivet.format_device(disk, fmt)

    def test_implicit_extended_partitions(self):
        """ Verify management of implicitly requested extended partition. """
        # By running partition allocation multiple times with enough partitions
        # to require an extended partition, we exercise the code that manages
        # the implicit extended partition.
        p1 = self.blivet.new_partition(size=Size("100 MiB"))
        self.blivet.create_device(p1)

        p2 = self.blivet.new_partition(size=Size("200 MiB"))
        self.blivet.create_device(p2)

        p3 = self.blivet.new_partition(size=Size("300 MiB"))
        self.blivet.create_device(p3)

        p4 = self.blivet.new_partition(size=Size("400 MiB"))
        self.blivet.create_device(p4)

        do_partitioning(self.blivet)

        # at this point there should be an extended partition
        self.assertIsNotNone(self.blivet.disks[0].format.extended_partition,
                             "no extended partition was created")

        # remove the last partition request and verify that the extended goes away as a result
        self.blivet.destroy_device(p4)
        do_partitioning(self.blivet)
        self.assertIsNone(self.blivet.disks[0].format.extended_partition,
                          "extended partition was not removed with last logical")

        p5 = self.blivet.new_partition(size=Size("500 MiB"))
        self.blivet.create_device(p5)

        do_partitioning(self.blivet)

        p6 = self.blivet.new_partition(size=Size("450 MiB"))
        self.blivet.create_device(p6)

        do_partitioning(self.blivet)

        self.assertIsNotNone(self.blivet.disks[0].format.extended_partition,
                             "no extended partition was created")

        self.blivet.do_it()

    def test_implicit_extended_partitions_installer_mode(self):
        flags.keep_empty_ext_partitions = False
        self.test_implicit_extended_partitions()
        flags.keep_empty_ext_partitions = True

    def test_explicit_extended_partitions(self):
        """ Verify that explicitly requested extended partitions work. """
        disk = self.blivet.disks[0]
        p1 = self.blivet.new_partition(size=Size("500 MiB"),
                                       part_type=parted.PARTITION_EXTENDED)
        self.blivet.create_device(p1)
        do_partitioning(self.blivet)

        self.assertEqual(p1.parted_partition.type, parted.PARTITION_EXTENDED)
        self.assertEqual(p1.parted_partition, disk.format.extended_partition)

        p2 = self.blivet.new_partition(size=Size("1 GiB"))
        self.blivet.create_device(p2)
        do_partitioning(self.blivet)

        self.assertEqual(p1.parted_partition, disk.format.extended_partition,
                         "user-specified extended partition was removed")

        self.blivet.do_it()
Beispiel #19
0
    '/mnt/sysimage/var',
}
REPO_DIRS = [
    '/etc/yum.repos.d', '/etc/anaconda.repos.d',
    '/tmp/updates/anaconda.repos.d', '/tmp/product/anaconda.repos.d'
]
YUM_REPOS_DIR = "/etc/yum.repos.d/"

from pyanaconda.product import productName, productVersion
USER_AGENT = "%s (anaconda)/%s" % (productName, productVersion)

# Bonus to required free space which depends on block size and rpm database size estimation.
# Every file could be aligned to fragment size so 4KiB * number_of_files should be a worst
# case scenario. 2KiB for RPM DB was acquired by testing.
# 6KiB = 4K(max default fragment size) + 2K(rpm db could be taken for a header file)
BONUS_SIZE_ON_FILE = Size("6 KiB")


def _failure_limbo():
    progressQ.send_quit(1)
    while True:
        time.sleep(10000)


def _df_map():
    """Return (mountpoint -> size available) mapping."""
    output = pyanaconda.iutil.execWithCapture('df', ['--output=target,avail'])
    output = output.rstrip()
    lines = output.splitlines()
    structured = {}
    for line in lines:
Beispiel #20
0
 def resize_slider_format(self, scale, value):
     # This makes the value displayed under the slider prettier than just a
     # single number.
     return str(Size(value))
Beispiel #21
0
    def test_lvm_parents(self):
        parent_device = self._get_parent_device()
        free_device = self._get_free_device(parent=parent_device)

        add_dialog = AddDialog(self.parent_window, parent_device, free_device,
                               [("free", free_device), ("free", self._get_free_device(size=Size("4 GiB"))), ("free", self._get_free_device(size=Size("4 GiB")))], [])
        add_dialog.devices_combo.set_active_id("lvm")

        # lvm allows multiple parents -- make sure we have all available and the right one is selected
        self.assertEqual(len(add_dialog.parents_store), 3)
        self.assertEqual(add_dialog.parents_store[0][0], parent_device)
        self.assertEqual(add_dialog.parents_store[0][1], free_device)
        self.assertTrue(add_dialog.parents_store[0][2])
        self.assertFalse(add_dialog.parents_store[1][2])  # other two free devices shouldn't be selected
        self.assertFalse(add_dialog.parents_store[2][2])
    def __init__(self, *args, **kwargs):
        # these are all absolutely required. not getting them is fatal.
        self._disks = kwargs.pop("disks")
        free = kwargs.pop("free")
        self.selected = kwargs.pop("selected")[:]
        self.name = kwargs.pop("name") or ""  # make sure it's a string
        self.device_type = kwargs.pop("device_type")
        self.storage = kwargs.pop("storage")

        # these are less critical
        self.raid_level = kwargs.pop("raid_level", None) or None  # not ""
        self.encrypted = kwargs.pop("encrypted", False)
        self.exists = kwargs.pop("exists", False)

        self.size_policy = kwargs.pop("size_policy", SIZE_POLICY_AUTO)
        self.size = kwargs.pop("size", Size(0))

        self._error = None
        GUIObject.__init__(self, *args, **kwargs)

        self._grabObjects()
        GUIDialogInputCheckHandler.__init__(self, self._save_button)

        # set up the dialog labels with device-type-specific text
        container_type = get_container_type(self.device_type)
        title_text = _(CONTAINER_DIALOG_TITLE) % {
            "container_type": _(container_type.name).upper()
        }
        self._title_label.set_text(title_text)

        dialog_text = _(CONTAINER_DIALOG_TEXT) % {
            "container_type": _(container_type.name).lower()
        }
        self._dialog_label.set_text(dialog_text)

        # populate the dialog widgets
        self._name_entry.set_text(self.name)

        # populate the store
        for disk in self._disks:
            self._store.append([
                disk.description,
                str(disk.size),
                str(free[disk.name][0]), disk.name, disk.id
            ])

        model = self._treeview.get_model()
        itr = model.get_iter_first()

        selected_ids = [d.id for d in self.selected]
        selection = self._treeview.get_selection()
        while itr:
            disk_id = model.get_value(itr, 4)
            if disk_id in selected_ids:
                selection.select_iter(itr)

            itr = model.iter_next(itr)

        # XXX how will this be related to the device encryption setting?
        self._encryptCheckbutton.set_active(self.encrypted)

        # set up the raid level combo
        # XXX how will this be related to the device raid level setting?
        self._raidStoreFilter.set_visible_func(self._raid_level_visible)
        self._raidStoreFilter.refilter()
        self._populate_raid()

        self._original_size = self.size
        self._original_size_text = self.size.human_readable(max_places=2)
        self._sizeEntry.set_text(self._original_size_text)
        if self.size_policy == SIZE_POLICY_AUTO:
            self._sizeCombo.set_active(0)
        elif self.size_policy == SIZE_POLICY_MAX:
            self._sizeCombo.set_active(1)
        else:
            self._sizeCombo.set_active(2)

        if self.exists:
            fancy_set_sensitive(self._name_entry, False)
            self._treeview.set_sensitive(False)
            fancy_set_sensitive(self._encryptCheckbutton, False)
            fancy_set_sensitive(self._sizeCombo, False)
            self._sizeEntry.set_sensitive(False)

        # Check that the container name configured is valid
        self.add_check(self._name_entry, self._checkNameEntry)
Beispiel #23
0
    def populate(self, disks):
        totalDisks = 0
        totalReclaimableSpace = Size(0)

        self._initialFreeSpace = Size(0)
        self._selectedReclaimableSpace = Size(0)

        canShrinkSomething = False

        free_space = self.storage.getFreeSpace(disks=disks)

        for disk in disks:
            # First add the disk itself.
            editable = not disk.protected

            if disk.partitioned:
                fstype = ""
                diskReclaimableSpace = Size(0)
            else:
                fstype = disk.format.name
                diskReclaimableSpace = disk.size

            itr = self._diskStore.append(None, [
                disk.id,
                "%s %s" %
                (disk.size.humanReadable(max_places=1), disk.description),
                fstype,
                "<span foreground='grey' style='italic'>%s total</span>",
                _(PRESERVE), editable, TY_NORMAL,
                self._get_tooltip(disk),
                int(disk.size), disk.name
            ])

            if disk.partitioned:
                # Then add all its partitions.
                for dev in self.storage.devicetree.getChildren(disk):
                    if dev.isExtended and disk.format.logicalPartitions:
                        continue

                    # Devices that are not resizable are still deletable.
                    if dev.resizable:
                        freeSize = dev.size - dev.minSize
                        resizeString = _("%(freeSize)s of %(devSize)s") \
                                       % {"freeSize": freeSize.humanReadable(max_places=1), "devSize": dev.size.humanReadable(max_places=1)}
                        if not dev.protected:
                            canShrinkSomething = True
                    else:
                        freeSize = dev.size
                        resizeString = "<span foreground='grey'>%s</span>" % \
                                escape_markup(_("Not resizeable"))

                    if dev.protected:
                        ty = TY_PROTECTED
                    else:
                        ty = TY_NORMAL

                    self._diskStore.append(itr, [
                        dev.id,
                        self._description(dev), dev.format.name, resizeString,
                        _(PRESERVE), not dev.protected, ty,
                        self._get_tooltip(dev),
                        int(dev.size), dev.name
                    ])
                    diskReclaimableSpace += freeSize

            # And then add another uneditable line that lists how much space is
            # already free in the disk.
            diskFree = free_space[disk.name][0]
            if diskFree >= Size("1MiB"):
                freeSpaceString = "<span foreground='grey' style='italic'>%s</span>" % \
                        escape_markup(_("Free space"))
                self._diskStore.append(itr, [
                    disk.id, freeSpaceString, "",
                    "<span foreground='grey' style='italic'>%s</span>" %
                    escape_markup(diskFree.humanReadable(max_places=1)),
                    NOTHING, False, TY_FREE_SPACE,
                    self._get_tooltip(disk), diskFree, ""
                ])
                self._initialFreeSpace += diskFree

            # And then go back and fill in the total reclaimable space for the
            # disk, now that we know what each partition has reclaimable.
            self._diskStore[itr][RECLAIMABLE_COL] = self._diskStore[itr][
                RECLAIMABLE_COL] % diskReclaimableSpace

            totalDisks += 1
            totalReclaimableSpace += diskReclaimableSpace

        self._update_labels(totalDisks, totalReclaimableSpace, 0)

        description = _(
            "You can remove existing file systems you no longer need to free up space "
            "for this installation.  Removing a file system will permanently delete all "
            "of the data it contains.")

        if canShrinkSomething:
            description += "\n\n"
            description += _(
                "There is also free space available in pre-existing file systems.  "
                "While it's risky and we recommend you back up your data first, you "
                "can recover that free disk space and make it available for this "
                "installation below.")

        self._reclaimDescLabel.set_text(description)
        self._update_reclaim_button(Size(0))
class ContainerDialog(GUIObject, GUIDialogInputCheckHandler):
    builderObjects = [
        "container_dialog", "disk_store", "container_disk_view",
        "containerRaidStoreFiltered", "containerRaidLevelLabel",
        "containerRaidLevelCombo", "raidLevelStore", "containerSizeCombo",
        "containerSizeEntry", "containerSizeLabel",
        "containerEncryptedCheckbox"
    ]
    mainWidgetName = "container_dialog"
    uiFile = "spokes/lib/custom_storage_helpers.glade"

    # If the user enters a smaller size, the GUI changes it to this value
    MIN_SIZE_ENTRY = Size("1 MiB")

    def __init__(self, *args, **kwargs):
        # these are all absolutely required. not getting them is fatal.
        self._disks = kwargs.pop("disks")
        free = kwargs.pop("free")
        self.selected = kwargs.pop("selected")[:]
        self.name = kwargs.pop("name") or ""  # make sure it's a string
        self.device_type = kwargs.pop("device_type")
        self.storage = kwargs.pop("storage")

        # these are less critical
        self.raid_level = kwargs.pop("raid_level", None) or None  # not ""
        self.encrypted = kwargs.pop("encrypted", False)
        self.exists = kwargs.pop("exists", False)

        self.size_policy = kwargs.pop("size_policy", SIZE_POLICY_AUTO)
        self.size = kwargs.pop("size", Size(0))

        self._error = None
        GUIObject.__init__(self, *args, **kwargs)

        self._grabObjects()
        GUIDialogInputCheckHandler.__init__(self, self._save_button)

        # set up the dialog labels with device-type-specific text
        container_type = get_container_type(self.device_type)
        title_text = _(CONTAINER_DIALOG_TITLE) % {
            "container_type": _(container_type.name).upper()
        }
        self._title_label.set_text(title_text)

        dialog_text = _(CONTAINER_DIALOG_TEXT) % {
            "container_type": _(container_type.name).lower()
        }
        self._dialog_label.set_text(dialog_text)

        # populate the dialog widgets
        self._name_entry.set_text(self.name)

        # populate the store
        for disk in self._disks:
            self._store.append([
                disk.description,
                str(disk.size),
                str(free[disk.name][0]), disk.name, disk.id
            ])

        model = self._treeview.get_model()
        itr = model.get_iter_first()

        selected_ids = [d.id for d in self.selected]
        selection = self._treeview.get_selection()
        while itr:
            disk_id = model.get_value(itr, 4)
            if disk_id in selected_ids:
                selection.select_iter(itr)

            itr = model.iter_next(itr)

        # XXX how will this be related to the device encryption setting?
        self._encryptCheckbutton.set_active(self.encrypted)

        # set up the raid level combo
        # XXX how will this be related to the device raid level setting?
        self._raidStoreFilter.set_visible_func(self._raid_level_visible)
        self._raidStoreFilter.refilter()
        self._populate_raid()

        self._original_size = self.size
        self._original_size_text = self.size.human_readable(max_places=2)
        self._sizeEntry.set_text(self._original_size_text)
        if self.size_policy == SIZE_POLICY_AUTO:
            self._sizeCombo.set_active(0)
        elif self.size_policy == SIZE_POLICY_MAX:
            self._sizeCombo.set_active(1)
        else:
            self._sizeCombo.set_active(2)

        if self.exists:
            fancy_set_sensitive(self._name_entry, False)
            self._treeview.set_sensitive(False)
            fancy_set_sensitive(self._encryptCheckbutton, False)
            fancy_set_sensitive(self._sizeCombo, False)
            self._sizeEntry.set_sensitive(False)

        # Check that the container name configured is valid
        self.add_check(self._name_entry, self._checkNameEntry)

    def _grabObjects(self):
        self._title_label = self.builder.get_object(
            "container_dialog_title_label")
        self._dialog_label = self.builder.get_object("container_dialog_label")
        self._error_label = self.builder.get_object("containerErrorLabel")

        self._name_entry = self.builder.get_object("container_name_entry")

        self._encryptCheckbutton = self.builder.get_object(
            "containerEncryptedCheckbox")
        self._raidStoreFilter = self.builder.get_object(
            "containerRaidStoreFiltered")

        self._store = self.builder.get_object("disk_store")
        self._treeview = self.builder.get_object("container_disk_view")

        self._sizeCombo = self.builder.get_object("containerSizeCombo")
        self._sizeEntry = self.builder.get_object("containerSizeEntry")

        self._raidLevelCombo = self.builder.get_object(
            "containerRaidLevelCombo")
        self._raidLevelLabel = self.builder.get_object(
            "containerRaidLevelLabel")

        self._save_button = self.builder.get_object("container_save_button")

    def _get_disk_by_id(self, disk_id):
        for disk in self._disks:
            if disk.id == disk_id:
                return disk

    def _save_clicked(self):
        if self.exists:
            return

        model, paths = self._treeview.get_selection().get_selected_rows()

        raid_level = selectedRaidLevel(self._raidLevelCombo)
        if raid_level:
            min_disks = raid_level.min_members
            if len(paths) < min_disks:
                self._error = (_(RAID_NOT_ENOUGH_DISKS) % {
                    "level": raid_level,
                    "min": min_disks,
                    "count": len(paths)
                })
                self._error_label.set_text(self._error)
                self.window.show_all()
                return

        idx = self._sizeCombo.get_active()
        if idx == 0:
            size = SIZE_POLICY_AUTO
        elif idx == 1:
            size = SIZE_POLICY_MAX
        elif idx == 2:
            if self._original_size_text != self._sizeEntry.get_text():
                size = size_from_entry(self._sizeEntry,
                                       lower_bound=self.MIN_SIZE_ENTRY,
                                       units=SIZE_UNITS_DEFAULT)
                if size is None:
                    size = SIZE_POLICY_MAX
            else:
                size = self._original_size

        # now save the changes

        self.selected = []
        for path in paths:
            itr = model.get_iter(path)
            disk_id = model.get_value(itr, 4)
            self.selected.append(self._get_disk_by_id(disk_id))

        self.name = self._name_entry.get_text().strip()
        self.raid_level = raid_level
        self.encrypted = self._encryptCheckbutton.get_active()
        self.size_policy = size

        self._error_label.set_text("")

    def run(self):
        while True:
            self._error = None
            rc = self.window.run()
            if rc == 1:
                # Save clicked and input validation passed, try saving it
                if self.on_ok_clicked():
                    self._save_clicked()

                    # If that failed, try again
                    if self._error:
                        continue
                    else:
                        break
                # Save clicked with invalid input, try again
                else:
                    continue
            else:
                # Cancel or something similar, just exit
                break

        self.window.destroy()
        return rc

    def on_size_changed(self, combo):
        active_index = combo.get_active()
        if active_index == 0:
            self._sizeEntry.set_sensitive(False)
        elif active_index == 1:
            self._sizeEntry.set_sensitive(False)
        else:
            self._sizeEntry.set_sensitive(True)

    def _raid_level_visible(self, model, itr, user_data):
        raid_level_str = model[itr][1]
        raid_level = raid.get_raid_level(
            raid_level_str) if raid_level_str != "none" else None
        return raid_level in containerRaidLevelsSupported(self.device_type)

    def _populate_raid(self):
        """ Set up the raid-specific portion of the device details.

            Hide the RAID level menu if this device type does not support RAID.
            Choose a default RAID level.
        """
        if not containerRaidLevelsSupported(self.device_type):
            for widget in [self._raidLevelLabel, self._raidLevelCombo]:
                really_hide(widget)
            return

        raid_level = self.raid_level or defaultContainerRaidLevel(
            self.device_type)
        raid_level_name = raidLevelSelection(raid_level)

        # Set a default RAID level in the combo.
        for (i, row) in enumerate(self._raidLevelCombo.get_model()):
            log.debug("container dialog: raid level %s", row[1])
            if row[1] == raid_level_name:
                self._raidLevelCombo.set_active(i)
                break

        for widget in [self._raidLevelLabel, self._raidLevelCombo]:
            really_show(widget)
        fancy_set_sensitive(self._raidLevelCombo, not self.exists)

    def _checkNameEntry(self, inputcheck):
        container_name = self.get_input(inputcheck.input_obj).strip()

        # Check that the container name is valid
        safename = self.storage.safe_device_name(container_name)
        if container_name != safename:
            return _("Invalid container name")

        return InputCheck.CHECK_OK
Beispiel #25
0
import os

import blivet
from blivet.size import Size
from blivet.util import set_up_logging, create_sparse_tempfile

set_up_logging()
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_tempfile("disk1", Size("100GiB"))
b.disk_images["disk1"] = disk1_file
disk2_file = create_sparse_tempfile("disk2", Size("100GiB"))
b.disk_images["disk2"] = disk2_file

b.reset()

try:
    disk1 = b.devicetree.get_device_by_name("disk1")
    disk2 = b.devicetree.get_device_by_name("disk2")

    b.initialize_disk(disk1)
    b.initialize_disk(disk2)

    # new partition on either disk1 or disk2 with base size 10GiB and growth
    # up to a maximum size of 50GiB
    dev = b.new_partition(size=Size("10MiB"), maxsize=Size("50GiB"),
                          grow=True, parents=[disk1, disk2])
    b.create_device(dev)

    # new partition on disk1 with base size 5GiB and unbounded growth and an
Beispiel #26
0
log = get_module_logger(__name__)

DNF_CACHE_DIR = '/tmp/dnf.cache'
DNF_PLUGINCONF_DIR = '/tmp/dnf.pluginconf'

# Bonus to required free space which depends on block size and
# rpm database size estimation. Every file could be aligned to
# fragment size so 4KiB * number_of_files should be a worst case
# scenario. 2KiB for RPM DB was acquired by testing.
#
#   4KiB = max default fragment size
#   2KiB = RPM DB could be taken for a header file
#   6KiB = 4KiB + 2KiB
#
DNF_EXTRA_SIZE_PER_FILE = Size("6 KiB")


class DNFManager(object):
    """The abstraction of the DNF base."""

    def __init__(self):
        self.__base = None
        self._ignore_missing_packages = False
        self._ignore_broken_packages = False
        self._download_location = None

    @property
    def _base(self):
        """The DNF base."""
        if self.__base is None:
Beispiel #27
0
 def testNegative(self):
     s = Size("-500MiB")
     self.assertEqual(s.humanReadable(), "-500 MiB")
     self.assertEqual(s.convertTo(B), -524288000)
Beispiel #28
0
    def test_btrfs_parents(self):
        parent_device = self._get_parent_device()
        free_device = self._get_free_device(parent=parent_device)

        add_dialog = AddDialog(self.parent_window, parent_device, free_device,
                               [("free", free_device), ("free", self._get_free_device(size=Size("200 MiB"))), ("free", self._get_free_device(size=Size("4 GiB")))], [])
        add_dialog.devices_combo.set_active_id("btrfs volume")

        # lvm allows multiple parents -- make sure we have all available (= larger than 256 MiB) and the right one is selected
        self.assertEqual(len(add_dialog.parents_store), 2)  # third device is smaller than min size for btrfs
        self.assertEqual(add_dialog.parents_store[0][0], parent_device)
        self.assertEqual(add_dialog.parents_store[0][1], free_device)
        self.assertTrue(add_dialog.parents_store[0][2])
        self.assertFalse(add_dialog.parents_store[1][2])  # other free device shouldn't be selected
Beispiel #29
0
 def _calculate_free_space(self):
     """Calculate the available space."""
     stat = os.statvfs(util.getSysroot())
     return Size(stat.f_bsize * stat.f_bfree)
Beispiel #30
0
 def spaceRequired(self):
     return Size(iutil.getDirSize("/") * 1024)
Beispiel #31
0
from blivet.size import Size

from pyanaconda.modules.storage.partitioning.automatic.utils import get_default_partitioning
from pyanaconda.modules.storage.partitioning.specification import PartSpec

from pyanaconda.core.configuration.anaconda import AnacondaConfiguration
from pyanaconda.core.configuration.base import ConfigurationError, create_parser, read_config
from pyanaconda.core.configuration.product import ProductLoader
from pyanaconda.product import trim_product_version_for_ui

PRODUCT_DIR = os.path.join(os.environ.get("ANACONDA_DATA"), "product.d")

SERVER_PARTITIONING = [
    PartSpec(mountpoint="/",
             size=Size("2GiB"),
             max_size=Size("15GiB"),
             grow=True,
             btr=True,
             lv=True,
             thin=True,
             encrypted=True),
    PartSpec(fstype="swap", lv=True, encrypted=True)
]

WORKSTATION_PARTITIONING = [
    PartSpec(mountpoint="/",
             size=Size("1GiB"),
             max_size=Size("70GiB"),
             grow=True,
             btr=True,
Beispiel #32
0
    def testRoundToNearest(self):
        self.assertEqual(size.ROUND_DEFAULT, size.ROUND_HALF_UP)

        s = Size("10.3 GiB")
        self.assertEqual(s.roundToNearest(GiB), Size("10 GiB"))
        self.assertEqual(s.roundToNearest(GiB, rounding=size.ROUND_DEFAULT),
                         Size("10 GiB"))
        self.assertEqual(s.roundToNearest(GiB, rounding=size.ROUND_DOWN),
                         Size("10 GiB"))
        self.assertEqual(s.roundToNearest(GiB, rounding=size.ROUND_UP),
                         Size("11 GiB"))
        # >>> Size("10.3 GiB").convertTo(MiB)
        # Decimal('10547.19999980926513671875')
        self.assertEqual(s.roundToNearest(MiB), Size("10547 MiB"))
        self.assertEqual(s.roundToNearest(MiB, rounding=size.ROUND_UP),
                         Size("10548 MiB"))
        self.assertIsInstance(s.roundToNearest(MiB), Size)
        with self.assertRaises(ValueError):
            s.roundToNearest(MiB, rounding='abc')

        # arbitrary decimal rounding constants are not allowed
        from decimal import ROUND_HALF_DOWN
        with self.assertRaises(ValueError):
            s.roundToNearest(MiB, rounding=ROUND_HALF_DOWN)

        s = Size("10.51 GiB")
        self.assertEqual(s.roundToNearest(GiB), Size("11 GiB"))
        self.assertEqual(s.roundToNearest(GiB, rounding=size.ROUND_DEFAULT),
                         Size("11 GiB"))
        self.assertEqual(s.roundToNearest(GiB, rounding=size.ROUND_DOWN),
                         Size("10 GiB"))
        self.assertEqual(s.roundToNearest(GiB, rounding=size.ROUND_UP),
                         Size("11 GiB"))

        s = Size("513 GiB")
        self.assertEqual(s.roundToNearest(GiB), s)
        self.assertEqual(s.roundToNearest(TiB), Size("1 TiB"))
        self.assertEqual(s.roundToNearest(TiB, rounding=size.ROUND_DOWN),
                         Size(0))

        # test Size parameters
        self.assertEqual(s.roundToNearest(Size("128 GiB")), Size("512 GiB"))
        self.assertEqual(s.roundToNearest(Size("1 KiB")), Size("513 GiB"))
        self.assertEqual(s.roundToNearest(Size("1 TiB")), Size("1 TiB"))
        self.assertEqual(s.roundToNearest(Size("1 TiB"), rounding=size.ROUND_DOWN), Size(0))
        self.assertEqual(s.roundToNearest(Size(0)), Size(0))
        self.assertEqual(s.roundToNearest(Size("13 GiB")), Size("507 GiB"))

        with self.assertRaises(ValueError):
            s.roundToNearest(Size("-1 B"))
Beispiel #33
0
 def __init__(self):
     self.downloads = collections.defaultdict(int)
     self.last_time = time.time()
     self.total_files = 0
     self.total_size = Size(0)
Beispiel #34
0
 def space_required(self):
     return super().space_required + Size(
         self._flatpak_payload.get_required_size())
Beispiel #35
0
    def test_human_readable_fractional_quantities(self):
        s = Size(0xfffffffffffff)
        self.assertEqual(s.human_readable(max_places=2), "4 PiB")
        s = Size(0xffff)
        # value is not exactly 64 KiB, but w/ 2 places, value is 64.00 KiB
        # so the trailing 0s are stripped.
        self.assertEqual(s.human_readable(max_places=2), "64 KiB")
        # since all significant digits are shown, there are no trailing 0s.
        self.assertEqual(s.human_readable(max_places=None),
                         "63.9990234375 KiB")

        # deviation is less than 1/2 of 1% of 1024
        s = Size(16384 - (1024 / 100 // 2))
        self.assertEqual(s.human_readable(max_places=2), "16 KiB")
        # deviation is greater than 1/2 of 1% of 1024
        s = Size(16384 - ((1024 / 100 // 2) + 1))
        self.assertEqual(s.human_readable(max_places=2), "15.99 KiB")

        s = Size(0x10000000000000)
        self.assertEqual(s.human_readable(max_places=2), "4 PiB")
Beispiel #36
0
    def testHumanReadable(self):
        s = Size(58929971L)
        self.assertEquals(s.humanReadable(), "56.2 MiB")

        s = Size(478360371L)
        self.assertEquals(s.humanReadable(), "456.2 MiB")

        # humanReable output should be the same as input for big enough sizes
        # and enough places and integer values
        s = Size("12.68 TiB")
        self.assertEquals(s.humanReadable(max_places=2), "12.68 TiB")
        s = Size("26.55 MiB")
        self.assertEquals(s.humanReadable(max_places=2), "26.55 MiB")
        s = Size("300 MiB")
        self.assertEquals(s.humanReadable(max_places=2), "300 MiB")

        # smaller unit should be used for small sizes
        s = Size("9.68 TiB")
        self.assertEquals(s.humanReadable(max_places=2), "9912.32 GiB")
        s = Size("4.29 MiB")
        self.assertEquals(s.humanReadable(max_places=2), "4392.96 KiB")
        s = Size("7.18 KiB")
        self.assertEquals(s.humanReadable(max_places=2), "7352 B")

        # rounding should work with max_places limitted
        s = Size("12.687 TiB")
        self.assertEquals(s.humanReadable(max_places=2), "12.69 TiB")
        s = Size("23.7874 TiB")
        self.assertEquals(s.humanReadable(max_places=3), "23.787 TiB")
        s = Size("12.6998 TiB")
        self.assertEquals(s.humanReadable(max_places=2), "12.7 TiB")
Beispiel #37
0
    def test_convert_to_with_size(self):
        s = Size(1835008)
        self.assertEqual(s.convert_to(Size(1)), s.convert_to(B))
        self.assertEqual(s.convert_to(Size(1024)), s.convert_to(KiB))
        self.assertEqual(Size(512).convert_to(Size(1024)), Decimal("0.5"))
        self.assertEqual(Size(1024).convert_to(Size(512)), Decimal(2))

        with self.assertRaises(ValueError):
            s.convert_to(Size(0))
Beispiel #38
0
def _destroy_device(storage, device):
    """Destroy the given device in the storage model.

    :param storage: an instance of Blivet
    :param device: an instance of a device
    """
    # Remove the device.
    if device.is_disk and device.partitioned and not device.format.supported:
        storage.recursive_remove(device)
    elif device.direct and not device.isleaf:
        # We shouldn't call this method for with non-leaf devices
        # except for those which are also directly accessible like
        # lvm snapshot origins and btrfs subvolumes that contain
        # other subvolumes.
        storage.recursive_remove(device)
    else:
        storage.destroy_device(device)

    # Initialize the disk.
    if device.is_disk:
        storage.initialize_disk(device)

    # Remove empty extended partitions.
    if getattr(device, "is_logical", False):
        storage.remove_empty_extended_partitions()

    # If we've just removed the last partition and the disk label
    # is preexisting, reinitialize the disk.
    if device.type == "partition" and device.exists and device.disk.format.exists:
        config = DiskInitializationConfig()

        if config.can_initialize(storage, device.disk):
            storage.initialize_disk(device.disk)

    # Get the device container.
    if hasattr(device, "vg"):
        container = device.vg
        device_type = devicefactory.get_device_type(device)
    elif hasattr(device, "volume"):
        container = device.volume
        device_type = devicefactory.DEVICE_TYPE_BTRFS
    else:
        container = None
        device_type = None

    # Adjust container to size of remaining devices, if auto-sized.
    if (container and not container.exists and container.children
            and container.size_policy == devicefactory.SIZE_POLICY_AUTO):
        # Create the device factory.
        factory = devicefactory.get_device_factory(
            storage,
            device_type=device_type,
            size=Size(0),
            disks=container.disks,
            container_name=container.name,
            container_encrypted=container.encrypted,
            container_raid_level=get_device_raid_level(container),
            container_size=container.size_policy,
        )

        # Configure the factory's devices.
        factory.configure()

    # Finally, remove empty parents of the device.
    for parent in device.parents:
        if not parent.children and not parent.is_disk:
            destroy_device(storage, parent)
Beispiel #39
0
 def test_partial_bytes(self):
     self.assertEqual(Size("1024.6"), Size(1024))
     self.assertEqual(Size("%s KiB" % (1 / 1025.0, )), Size(0))
     self.assertEqual(Size("%s KiB" % (1 / 1023.0, )), Size(1))
Beispiel #40
0
    def test_add_partition(self):
        with sparsetmpfile("addparttest", Size("50 MiB")) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path, exists=False, label_type="msdos")

            free = disk.format.parted_disk.getFreeSpaceRegions()[0]

            #
            # add a partition with an unaligned size
            #
            self.assertEqual(len(disk.format.partitions), 0)
            part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                 Size("10 MiB") - Size(37))
            self.assertEqual(len(disk.format.partitions), 1)

            # an unaligned size still yields an aligned partition
            alignment = disk.format.alignment
            geom = part.geometry
            sector_size = Size(geom.device.sectorSize)
            self.assertEqual(alignment.isAligned(free, geom.start), True)
            self.assertEqual(alignment.isAligned(free, geom.end + 1), True)
            self.assertEqual(part.geometry.length, int(Size("10 MiB") // sector_size))

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # adding a partition smaller than the optimal io size should yield
            # a partition aligned using the minimal io size instead
            #
            opt_str = 'parted.Device.optimumAlignment'
            min_str = 'parted.Device.minimumAlignment'
            opt_al = parted.Alignment(offset=0, grainSize=8192)  # 4 MiB
            min_al = parted.Alignment(offset=0, grainSize=2048)  # 1 MiB
            disk.format._minimal_alignment = None  # drop cache
            disk.format._optimal_alignment = None  # drop cache
            with patch(opt_str, opt_al) as optimal, patch(min_str, min_al) as minimal:
                optimal_end = disk.format.get_end_alignment(alignment=optimal)
                minimal_end = disk.format.get_end_alignment(alignment=minimal)

                sector_size = Size(disk.format.sector_size)
                length = 4096  # 2 MiB
                size = Size(sector_size * length)
                part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                     size)
                self.assertEqual(part.geometry.length, length)
                self.assertEqual(optimal.isAligned(free, part.geometry.start),
                                 False)
                self.assertEqual(minimal.isAligned(free, part.geometry.start),
                                 True)
                self.assertEqual(optimal_end.isAligned(free, part.geometry.end),
                                 False)
                self.assertEqual(minimal_end.isAligned(free, part.geometry.end),
                                 True)

                disk.format.remove_partition(part)
                self.assertEqual(len(disk.format.partitions), 0)

            #
            # adding a partition smaller than the minimal io size should yield
            # a partition whose size is aligned up to the minimal io size
            #
            opt_str = 'parted.Device.optimumAlignment'
            min_str = 'parted.Device.minimumAlignment'
            opt_al = parted.Alignment(offset=0, grainSize=8192)  # 4 MiB
            min_al = parted.Alignment(offset=0, grainSize=2048)  # 1 MiB
            disk.format._minimal_alignment = None  # drop cache
            disk.format._optimal_alignment = None  # drop cache
            with patch(opt_str, opt_al) as optimal, patch(min_str, min_al) as minimal:
                optimal_end = disk.format.get_end_alignment(alignment=optimal)
                minimal_end = disk.format.get_end_alignment(alignment=minimal)

                sector_size = Size(disk.format.sector_size)
                length = 1024  # 512 KiB
                size = Size(sector_size * length)
                part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                     size)
                self.assertEqual(part.geometry.length, min_al.grainSize)
                self.assertEqual(optimal.isAligned(free, part.geometry.start),
                                 False)
                self.assertEqual(minimal.isAligned(free, part.geometry.start),
                                 True)
                self.assertEqual(optimal_end.isAligned(free, part.geometry.end),
                                 False)
                self.assertEqual(minimal_end.isAligned(free, part.geometry.end),
                                 True)

                disk.format.remove_partition(part)
                self.assertEqual(len(disk.format.partitions), 0)

            #
            # add a partition with an unaligned start sector
            #
            start_sector = 5003
            end_sector = 15001
            part = add_partition(disk.format, free, parted.PARTITION_NORMAL,
                                 None, start_sector, end_sector)
            self.assertEqual(len(disk.format.partitions), 1)

            # start and end sectors are exactly as specified
            self.assertEqual(part.geometry.start, start_sector)
            self.assertEqual(part.geometry.end, end_sector)

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 0)

            #
            # fail: add a logical partition to a primary free region
            #
            with six.assertRaisesRegex(self, parted.PartitionException,
                                       "no extended partition"):
                part = add_partition(disk.format, free, parted.PARTITION_LOGICAL,
                                     Size("10 MiB"))

            # add an extended partition to the disk
            placeholder = add_partition(disk.format, free,
                                        parted.PARTITION_NORMAL, Size("10 MiB"))
            all_free = disk.format.parted_disk.getFreeSpaceRegions()
            add_partition(disk.format, all_free[1],
                          parted.PARTITION_EXTENDED, Size("30 MiB"),
                          alignment.alignUp(all_free[1],
                                            placeholder.geometry.end))

            disk.format.remove_partition(placeholder)
            self.assertEqual(len(disk.format.partitions), 1)
            all_free = disk.format.parted_disk.getFreeSpaceRegions()

            #
            # add a logical partition to an extended free regions
            #
            part = add_partition(disk.format, all_free[1],
                                 parted.PARTITION_LOGICAL,
                                 Size("10 MiB"), all_free[1].start)
            self.assertEqual(part.type, parted.PARTITION_LOGICAL)

            disk.format.remove_partition(part)
            self.assertEqual(len(disk.format.partitions), 1)

            #
            # fail: add a primary partition to an extended free region
            #
            with six.assertRaisesRegex(self, parted.PartitionException, "overlap"):
                part = add_partition(disk.format, all_free[1],
                                     parted.PARTITION_NORMAL,
                                     Size("10 MiB"), all_free[1].start)
 def get_required_device_size_test(self):
     """Test GetRequiredDeviceSize."""
     required_size = self.interface.GetRequiredDeviceSize(
         Size("1 GiB").get_bytes())
     self.assertEqual(
         Size("1280 MiB").get_bytes(), required_size, Size(required_size))
Beispiel #42
0
    def test_msdos_disk_chunk2(self):
        disk_size = Size("100 MiB")
        with sparsetmpfile("chunktest", disk_size) as disk_file:
            disk = DiskFile(disk_file)
            disk.format = get_format("disklabel", device=disk.path, exists=False, label_type="msdos")

            p1 = PartitionDevice("p1", size=Size("10 MiB"), grow=True)
            p2 = PartitionDevice("p2", size=Size("30 MiB"), grow=True)

            # format max size should be reflected in request max growth
            fmt = get_format("dummy")
            fmt._max_size = Size("12 MiB")
            p3 = PartitionDevice("p3", size=Size("10 MiB"), grow=True,
                                 fmt=fmt)

            p4 = PartitionDevice("p4", size=Size("7 MiB"))

            # partition max size should be reflected in request max growth
            p5 = PartitionDevice("p5", size=Size("5 MiB"), grow=True,
                                 maxsize=Size("6 MiB"))

            disks = [disk]
            partitions = [p1, p2, p3, p4, p5]
            free = get_free_regions([disk])
            self.assertEqual(len(free), 1,
                             "free region count %d not expected" % len(free))

            b = Mock(spec=Blivet)
            allocate_partitions(b, disks, partitions, free)

            requests = [PartitionRequest(p) for p in partitions]
            chunk = DiskChunk(free[0], requests=requests)

            self.assertEqual(len(chunk.requests), len(partitions))

            # parted reports a first free sector of 32 for disk files. whatever.
            length_expected = 204768
            self.assertEqual(chunk.length, length_expected)

            growable = [p for p in partitions if p.req_grow]
            fixed = [p for p in partitions if not p.req_grow]
            base_expected = sum(p.parted_partition.geometry.length for p in growable)
            self.assertEqual(chunk.base, base_expected)

            base_fixed = sum(p.parted_partition.geometry.length for p in fixed)
            pool_expected = chunk.length - base_expected - base_fixed
            self.assertEqual(chunk.pool, pool_expected)

            self.assertEqual(chunk.done, False)

            # since p5 is not growable it is initially done
            self.assertEqual(chunk.remaining, 4)

            chunk.grow_requests()

            #
            # validate the growth (in sectors)
            #
            # The chunk length is 204768.
            # Request bases:
            #   p1 20480
            #   p2 61440
            #   p3 20480
            #   p4 14336 (not included in chunk base since it isn't growable)
            #   p5 10240
            #
            # The chunk has a base 112640 and a pool of 77792.
            #
            # Request max growth:
            #   p1 0
            #   p2 0
            #   p3 4096
            #   p4 0
            #   p5 2048
            #
            # The first round should allocate to p1, p2, p3, p5 at a ratio of
            # 2:6:2:1, which is 14144, 42432, 14144, 7072. Due to max growth,
            # p3 and p5 will be limited and the extra (10048, 5024) will remain
            # in the pool. In the second round the remaining requests will be
            # p1 and p2. They will divide up the pool of 15072 at a ratio of
            # 1:3, which is 3768 and 11304. At this point the pool should be
            # empty.
            #
            # Total growth:
            #   p1 17912
            #   p2 53736
            #   p3 4096
            #   p4 0
            #   p5 2048
            #
            self.assertEqual(chunk.done, True)
            self.assertEqual(chunk.pool, 0)
            self.assertEqual(chunk.remaining, 2)    # p1, p2 have no max

            # chunk.requests got sorted, so use the list whose order we know
            self.assertEqual(requests[0].growth, 17912)
            self.assertEqual(requests[1].growth, 53736)
            self.assertEqual(requests[2].growth, 4096)
            self.assertEqual(requests[3].growth, 0)
            self.assertEqual(requests[4].growth, 2048)
Beispiel #43
0
    def test_human_readable(self):
        s = Size(58929971)
        self.assertEqual(s.human_readable(), "56.2 MiB")

        s = Size(478360371)
        self.assertEqual(s.human_readable(), "456.2 MiB")

        # human_reable output should be the same as input for big enough sizes
        # and enough places and integer values
        s = Size("12.68 TiB")
        self.assertEqual(s.human_readable(max_places=2), "12.68 TiB")
        s = Size("26.55 MiB")
        self.assertEqual(s.human_readable(max_places=2), "26.55 MiB")
        s = Size("300 MiB")
        self.assertEqual(s.human_readable(max_places=2), "300 MiB")

        # rounding should work with max_places limitted
        s = Size("12.687 TiB")
        self.assertEqual(s.human_readable(max_places=2), "12.69 TiB")
        s = Size("23.7874 TiB")
        self.assertEqual(s.human_readable(max_places=3), "23.787 TiB")
        s = Size("12.6998 TiB")
        self.assertEqual(s.human_readable(max_places=2), "12.7 TiB")

        # byte values close to multiples of 2 are shown without trailing zeros
        s = Size(0xff)
        self.assertEqual(s.human_readable(max_places=2), "255 B")

        # a fractional quantity is shown if the value deviates
        # from the whole number of units by more than 1%
        s = Size(16384 - (1024 / 100 + 1))
        self.assertEqual(s.human_readable(max_places=2), "15.99 KiB")

        # if max_places is set to None, all digits are displayed
        s = Size(0xfffffffffffff)
        self.assertEqual(s.human_readable(max_places=None), "3.99999999999999911182158029987476766109466552734375 PiB")
        s = Size(0x10000)
        self.assertEqual(s.human_readable(max_places=None), "64 KiB")
        s = Size(0x10001)
        self.assertEqual(s.human_readable(max_places=None), "64.0009765625 KiB")

        # test a very large quantity with no associated abbreviation or prefix
        s = Size(1024 ** 9)
        self.assertEqual(s.human_readable(max_places=2), "1024 YiB")
        s = Size(1024 ** 9 - 1)
        self.assertEqual(s.human_readable(max_places=2), "1024 YiB")
        s = Size(1024 ** 10)
        self.assertEqual(s.human_readable(max_places=2), "1048576 YiB")
Beispiel #44
0
    def test_vgchunk(self):
        pv = StorageDevice("pv1", size=Size("40 GiB"),
                           fmt=get_format("lvmpv"))
        vg = LVMVolumeGroupDevice("vg", parents=[pv])
        lv1 = LVMLogicalVolumeDevice("lv1", parents=[vg],
                                     size=Size("1 GiB"), grow=True)
        lv2 = LVMLogicalVolumeDevice("lv2", parents=[vg],
                                     size=Size("10 GiB"), grow=True)
        lv3 = LVMLogicalVolumeDevice("lv3", parents=[vg],
                                     size=Size("10 GiB"), grow=True,
                                     maxsize=Size("12 GiB"))

        req1 = LVRequest(lv1)
        req2 = LVRequest(lv2)
        req3 = LVRequest(lv3)
        chunk = VGChunk(vg, requests=[req1, req2, req3])

        self.assertEqual(chunk.length, vg.extents)
        self.assertEqual(chunk.pool, vg.free_extents)
        base_size = vg.align(sum((lv.size for lv in vg.lvs), Size(0)), roundup=True)
        base = base_size / vg.pe_size
        self.assertEqual(chunk.base, base)

        # default extent size is 4 MiB
        self.assertEqual(chunk.length_to_size(4), Size("16 MiB"))
        self.assertEqual(chunk.size_to_length(Size("33 MiB")), 8)
        self.assertEqual(chunk.has_growable, True)

        self.assertEqual(chunk.remaining, 3)
        self.assertEqual(chunk.done, False)

        chunk.grow_requests()

        # the chunk is done growing since its pool has been exhausted
        self.assertEqual(chunk.done, True)

        # there are still two requests remaining since lv1 and lv2 have no max
        self.assertEqual(chunk.remaining, 2)

        #
        # validate the resulting growth
        #
        # lv1 has size 1 GiB (256 extents) and is growable with no limit
        # lv2 has size 10 GiB (2560 extents) and is growable with no limit
        # lv3 has size 10 GiB (2560 extents) and is growable with a max size of
        #     12 GiB (max growth of 512 extents)
        #
        # The vg initially has 4863 free extents.
        # The growth ratio should be 1:10:10.
        #
        # The first pass through should allocate 231 extents to lv1 and 2315
        # extents to each of lv2 and lv3, leaving one remaining extent, but
        # it should reclaim 1803 extents from lv3 since it has a maximum growth
        # of 512 extents (2 GiB).
        #
        # The second pass should then split up the remaining 1805 extents
        # between lv1 and lv2 at a ratio of 1:10, which ends up being 164 for
        # lv1 and 1640 for lv2. The remaining extent goes to lv2 because it is
        # first in the list after sorting with blivet.partitioning.lv_compare.
        #
        # Grand totals should be as follows:
        # lv1 should grow by 395 extents, or 1.54 GiB
        # lv2 should grow by 3956 extents, or 15.45 GiB
        # lv3 should grow by 512 extents, or 2 GiB
        self.assertEqual(req1.growth, 395)
        self.assertEqual(req2.growth, 3956)
        self.assertEqual(req3.growth, 512)
Beispiel #45
0
    def on_back_clicked(self, button):
        # We can't exit early if it looks like nothing has changed because the
        # user might want to change settings presented in the dialogs shown from
        # within this method.

        # Do not enter this method multiple times if user clicking multiple times
        # on back button
        if self._back_clicked:
            return
        else:
            self._back_clicked = True

        # Remove all non-existing devices if autopart was active when we last
        # refreshed.
        if self._previous_autopart:
            self._previous_autopart = False
            for partition in self.storage.partitions[:]:
                # check if it's been removed in a previous iteration
                if not partition.exists and \
                   partition in self.storage.partitions:
                    self.storage.recursiveRemove(partition)

        # make sure no containers were split up by the user's disk selection
        self.clear_info()
        self.errors = checkDiskSelection(self.storage, self.selected_disks)
        if self.errors:
            # The disk selection has to make sense before we can proceed.
            self.set_error(
                _("There was a problem with your disk selection. "
                  "Click here for details."))
            self._back_clicked = False
            return

        # hide/unhide disks as requested
        for disk in self.disks:
            if disk.name not in self.selected_disks and \
               disk in self.storage.devices:
                self.storage.devicetree.hide(disk)
            elif disk.name in self.selected_disks and \
                 disk not in self.storage.devices:
                self.storage.devicetree.unhide(disk)

        # show the installation options dialog
        disks = [d for d in self.disks if d.name in self.selected_disks]
        disks_size = sum((d.size for d in disks), Size(0))

        # No disks selected?  The user wants to back out of the storage spoke.
        if not disks:
            NormalSpoke.on_back_clicked(self, button)
            return

        if arch.isS390():
            # check for unformatted DASDs and launch dasdfmt if any discovered
            dasds = self.storage.devicetree.make_unformatted_dasd_list(disks)
            if len(dasds) > 0:
                # We want to apply current selection before running dasdfmt to
                # prevent this information from being lost afterward
                applyDiskSelection(self.storage, self.data,
                                   self.selected_disks)
                dialog = DasdFormatDialog(self.data, self.storage, dasds)
                ignoreEscape(dialog.window)
                rc = self.run_lightbox_dialog(dialog)
                if rc == 1:
                    # User hit OK on the dialog
                    self.refresh()
                elif rc == 2:
                    # User clicked uri to return to hub.
                    NormalSpoke.on_back_clicked(self, button)
                    return
                elif rc != 2:
                    # User either hit cancel on the dialog or closed it via escape,
                    # there was no formatting done.
                    # NOTE: rc == 2 means the user clicked on the link that takes t
                    # back to the hub.
                    self._back_clicked = False
                    return

        # Figure out if the existing disk labels will work on this platform
        # you need to have at least one of the platform's labels in order for
        # any of the free space to be useful.
        disk_labels = set(disk.format.labelType for disk in disks
                          if hasattr(disk.format, "labelType"))
        platform_labels = set(platform.diskLabelTypes)
        if disk_labels and platform_labels.isdisjoint(disk_labels):
            disk_free = 0
            fs_free = 0
            log.debug("Need disklabel: %s have: %s",
                      ", ".join(platform_labels), ", ".join(disk_labels))
        else:
            free_space = self.storage.getFreeSpace(
                disks=disks, clearPartType=CLEARPART_TYPE_NONE)
            disk_free = sum(f[0] for f in free_space.values())
            fs_free = sum(f[1] for f in free_space.values())

        required_space = self.payload.spaceRequired
        auto_swap = sum((r.size for r in self.storage.autoPartitionRequests
                         if r.fstype == "swap"), Size(0))
        if self.autopart and auto_swap == Size(0):
            # autopartitioning requested, but not applied yet (=> no auto swap
            # requests), ask user for enough space to fit in the suggested swap
            auto_swap = autopart.swapSuggestion()

        log.debug("disk free: %s  fs free: %s  sw needs: %s  auto swap: %s",
                  disk_free, fs_free, required_space, auto_swap)

        if disk_free >= required_space + auto_swap:
            dialog = None
        elif disks_size >= required_space:
            if self._customPart.get_active() or self._reclaim.get_active():
                dialog = None
            else:
                dialog = NeedSpaceDialog(self.data, payload=self.payload)
                dialog.refresh(required_space, auto_swap, disk_free, fs_free)
                rc = self.run_lightbox_dialog(dialog)
        else:
            dialog = NoSpaceDialog(self.data, payload=self.payload)
            dialog.refresh(required_space, auto_swap, disk_free, fs_free)
            rc = self.run_lightbox_dialog(dialog)

        if not dialog:
            # Plenty of room - there's no need to pop up a dialog, so just send
            # the user to wherever they asked to go.  That's either the custom
            # spoke or the hub.
            #    - OR -
            # Not enough room, but the user checked the reclaim button.

            self.encrypted = self._encrypted.get_active()

            if self._customPart.get_active():
                self.autopart = False
                self.skipTo = "CustomPartitioningSpoke"
            else:
                self.autopart = True

                # We might first need to ask about an encryption passphrase.
                if not self._check_encrypted():
                    self._back_clicked = False
                    return

                # Oh and then we might also want to go to the reclaim dialog.
                if self._reclaim.get_active():
                    self.apply()
                    if not self._show_resize_dialog(disks):
                        # User pressed cancel on the reclaim dialog, so don't leave
                        # the storage spoke.
                        self._back_clicked = False
                        return
        elif rc == RESPONSE_CANCEL:
            # A cancel button was clicked on one of the dialogs.  Stay on this
            # spoke.  Generally, this is because the user wants to add more disks.
            self._back_clicked = False
            return
        elif rc == RESPONSE_MODIFY_SW:
            # The "Fedora software selection" link was clicked on one of the
            # dialogs.  Send the user to the software spoke.
            self.skipTo = "SoftwareSelectionSpoke"
        elif rc == RESPONSE_RECLAIM:
            # Not enough space, but the user can make enough if they do some
            # work and free up space.
            self.encrypted = self._encrypted.get_active()

            if not self._check_encrypted():
                return

            self.apply()
            if not self._show_resize_dialog(disks):
                # User pressed cancel on the reclaim dialog, so don't leave
                # the storage spoke.
                self._back_clicked = False
                return

            # And then go to the custom partitioning spoke if they chose to
            # do so.
            if self._customPart.get_active():
                self.autopart = False
                self.skipTo = "CustomPartitioningSpoke"
            else:
                self.autopart = True
        elif rc == RESPONSE_QUIT:
            # Not enough space, and the user can't do anything about it so
            # they chose to quit.
            raise SystemExit("user-selected exit")
        else:
            # I don't know how we'd get here, but might as well have a
            # catch-all.  Just stay on this spoke.
            self._back_clicked = False
            return

        if self.autopart:
            refreshAutoSwapSize(self.storage)
        self.applyOnSkip = True
        NormalSpoke.on_back_clicked(self, button)
Beispiel #46
0
 def space_required(self):
     # We don't have this data with OSTree at the moment
     return Size("500 MB")
Beispiel #47
0
    def get_free_space(self, disks=None, clear_part_type=None):  # pylint: disable=arguments-differ
        """ Return a dict with free space info for each disk.

             The dict values are 2-tuples: (disk_free, fs_free). fs_free is
             space available by shrinking filesystems. disk_free is space not
             allocated to any partition.

             disks and clear_part_type allow specifying a set of disks other than
             self.disks and a clear_part_type value other than
             self.config.clear_part_type.

             :keyword disks: overrides :attr:`disks`
             :type disks: list
             :keyword clear_part_type: overrides :attr:`self.config.clear_part_type`
             :type clear_part_type: int
             :returns: dict with disk name keys and tuple (disk, fs) free values
             :rtype: dict

            .. note::

                The free space values are :class:`blivet.size.Size` instances.

        """

        # FIXME: we should definitely do something with this method -- it takes
        # different parameters than get_free_space from Blivet and does
        # different things too

        if disks is None:
            disks = self.disks

        if clear_part_type is None:
            clear_part_type = self.config.clear_part_type

        free = {}
        for disk in disks:
            should_clear = self.should_clear(disk,
                                             clear_part_type=clear_part_type,
                                             clear_part_disks=[disk.name])
            if should_clear:
                free[disk.name] = (disk.size, Size(0))
                continue

            disk_free = Size(0)
            fs_free = Size(0)
            if disk.partitioned:
                disk_free = disk.format.free
                for partition in (p for p in self.partitions
                                  if p.disk == disk):
                    # only check actual filesystems since lvm &c require a bunch of
                    # operations to translate free filesystem space into free disk
                    # space
                    should_clear = self.should_clear(
                        partition,
                        clear_part_type=clear_part_type,
                        clear_part_disks=[disk.name])
                    if should_clear:
                        disk_free += partition.size
                    elif hasattr(partition.format, "free"):
                        fs_free += partition.format.free
            elif hasattr(disk.format, "free"):
                fs_free = disk.format.free
            elif disk.format.type is None:
                disk_free = disk.size

            free[disk.name] = (disk_free, fs_free)

        return free
Beispiel #48
0
def get_container_size_policy_by_number(number):
    """Get a container size policy by the given number."""
    if number <= 0:
        return number

    return Size(number)
Beispiel #49
0
    def testHumanReadable(self):
        s = Size(58929971)
        self.assertEqual(s.humanReadable(), "56.2 MiB")

        s = Size(478360371)
        self.assertEqual(s.humanReadable(), "456.2 MiB")

        # humanReable output should be the same as input for big enough sizes
        # and enough places and integer values
        s = Size("12.68 TiB")
        self.assertEqual(s.humanReadable(max_places=2), "12.68 TiB")
        s = Size("26.55 MiB")
        self.assertEqual(s.humanReadable(max_places=2), "26.55 MiB")
        s = Size("300 MiB")
        self.assertEqual(s.humanReadable(max_places=2), "300 MiB")

        # when min_value is 10 and single digit on left of decimal, display
        # with smaller unit.
        s = Size("9.68 TiB")
        self.assertEqual(s.humanReadable(max_places=2, min_value=10), "9912.32 GiB")
        s = Size("4.29 MiB")
        self.assertEqual(s.humanReadable(max_places=2, min_value=10), "4392.96 KiB")
        s = Size("7.18 KiB")
        self.assertEqual(s.humanReadable(max_places=2, min_value=10), "7352 B")

        # rounding should work with max_places limitted
        s = Size("12.687 TiB")
        self.assertEqual(s.humanReadable(max_places=2), "12.69 TiB")
        s = Size("23.7874 TiB")
        self.assertEqual(s.humanReadable(max_places=3), "23.787 TiB")
        s = Size("12.6998 TiB")
        self.assertEqual(s.humanReadable(max_places=2), "12.7 TiB")

        # byte values close to multiples of 2 are shown without trailing zeros
        s = Size(0xff)
        self.assertEqual(s.humanReadable(max_places=2), "255 B")
        s = Size(8193)
        self.assertEqual(s.humanReadable(max_places=2, min_value=10), "8193 B")

        # a fractional quantity is shown if the value deviates
        # from the whole number of units by more than 1%
        s = Size(16384 - (1024/100 + 1))
        self.assertEqual(s.humanReadable(max_places=2), "15.99 KiB")

        # if max_places is set to None, all digits are displayed
        s = Size(0xfffffffffffff)
        self.assertEqual(s.humanReadable(max_places=None), "3.9999999999999991118215803 PiB")
        s = Size(0x10000)
        self.assertEqual(s.humanReadable(max_places=None), "64 KiB")
        s = Size(0x10001)
        self.assertEqual(s.humanReadable(max_places=None), "64.0009765625 KiB")

        # test a very large quantity with no associated abbreviation or prefix
        s = Size(1024**9)
        self.assertEqual(s.humanReadable(max_places=2), "1024 YiB")
        s = Size(1024**9 - 1)
        self.assertEqual(s.humanReadable(max_places=2), "1024 YiB")
        s = Size(1024**9 + 1)
        self.assertEqual(s.humanReadable(max_places=2, strip=False), "1024.00 YiB")
        s = Size(1024**10)
        self.assertEqual(s.humanReadable(max_places=2), "1048576 YiB")
Beispiel #50
0
    def testHumanReadable(self):
        s = Size(bytes=58929971L)
        self.assertEquals(s.humanReadable(), "56.19 MiB")

        s = Size(bytes=478360371L)
        self.assertEquals(s.humanReadable(), "456.19 MiB")