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())
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)
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")
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)
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")
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")
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")
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")
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))
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)
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
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)
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"))
def test_segative(self): s = Size("-500MiB") self.assertEqual(s.human_readable(), "-500 MiB") self.assertEqual(s.convert_to(B), -524288000)
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")
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)
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"))
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()
'/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:
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))
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)
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
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
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:
def testNegative(self): s = Size("-500MiB") self.assertEqual(s.humanReadable(), "-500 MiB") self.assertEqual(s.convertTo(B), -524288000)
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
def _calculate_free_space(self): """Calculate the available space.""" stat = os.statvfs(util.getSysroot()) return Size(stat.f_bsize * stat.f_bfree)
def spaceRequired(self): return Size(iutil.getDirSize("/") * 1024)
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,
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"))
def __init__(self): self.downloads = collections.defaultdict(int) self.last_time = time.time() self.total_files = 0 self.total_size = Size(0)
def space_required(self): return super().space_required + Size( self._flatpak_payload.get_required_size())
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")
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")
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))
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)
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))
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))
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)
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")
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)
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)
def space_required(self): # We don't have this data with OSTree at the moment return Size("500 MB")
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
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)
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")
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")