diff --git a/blivetgui/blivet_utils.py b/blivetgui/blivet_utils.py index e2f0a089..6fb6d77b 100644 --- a/blivetgui/blivet_utils.py +++ b/blivetgui/blivet_utils.py @@ -24,6 +24,7 @@ import blivet from blivet.devices import PartitionDevice, LUKSDevice, LVMVolumeGroupDevice, BTRFSVolumeDevice, BTRFSSubVolumeDevice, MDRaidArrayDevice +from blivet.devices import StratisFilesystemDevice, StratisPoolDevice from blivet.formats import DeviceFormat from blivet.size import Size @@ -213,6 +214,7 @@ def get_group_devices(self): devices["lvm"] = self.storage.vgs devices["raid"] = self.storage.mdarrays devices["btrfs"] = self.storage.btrfs_volumes + devices["stratis"] = self.storage.stratis_pools return devices @@ -248,14 +250,14 @@ def get_group_device(self, blivet_device): """ # already a group device - if blivet_device.type in ("btrfs volume", "lvmvg", "mdarray"): + if blivet_device.type in ("btrfs volume", "lvmvg", "mdarray", "stratis pool"): return blivet_device # encrypted group device -> get the luks device instead if blivet_device.format.type in ("luks", "integrity"): blivet_device = self.get_luks_device(blivet_device) - if not blivet_device.format or blivet_device.format.type not in ("lvmpv", "btrfs", "mdmember", "luks"): + if not blivet_device.format or blivet_device.format.type not in ("lvmpv", "btrfs", "mdmember", "luks", "stratis"): return None if len(blivet_device.children) != 1: return None @@ -296,7 +298,7 @@ def get_children(self, blivet_device): childs = blivet_device.children - if blivet_device.type == "lvmvg" and blivet_device.free_space > blivet.size.Size(0): + if blivet_device.type in ("lvmvg", "stratis pool") and blivet_device.free_space > blivet.size.Size(0): childs.append(FreeSpaceDevice(blivet_device.free_space, self.storage.next_id, None, None, [blivet_device])) return childs @@ -323,6 +325,11 @@ def get_disk_children(self, blivet_device): btrfs_volume = blivet_device.children[0] return ProxyDataContainer(partitions=[btrfs_volume], extended=None, logicals=None) + if blivet_device.format and blivet_device.format.type == "stratis" and blivet_device.children: + # stratis pool on raw device + stratis_pool = blivet_device.children[0] + return ProxyDataContainer(partitions=[stratis_pool], extended=None, logicals=None) + if blivet_device.format and blivet_device.format.type in ("luks", "integrity"): if blivet_device.children: luks = self.get_luks_device(blivet_device) @@ -449,6 +456,9 @@ def get_roots(self, blivet_device): elif blivet_device.type in ("mdarray", "btrfs volume"): for member in blivet_device.members: roots.add(self._get_root_device(member)) + elif blivet_device.type == "stratis pool": + for blockdev in blivet_device.blockdevs: + roots.add(self._get_root_device(blockdev)) elif blivet_device.type in ("luks/dm-crypt", "integrity/dm-crypt"): roots.add(self._get_root_device(blivet_device.raw_device)) @@ -505,6 +515,12 @@ def get_free_device(self, blivet_device): dev_id=self.storage.next_id, start=None, end=None, parents=[blivet_device]) + # Stratis Pool -- size of the filesystems is fixed + elif blivet_device.type == "stratis pool": + return FreeSpaceDevice(free_size=blivet_device.free_space, + dev_id=self.storage.next_id, + start=None, end=None, + parents=[blivet_device]) # something else, just return size of the device and hope for the best else: return FreeSpaceDevice(free_size=blivet_device.size, @@ -628,7 +644,7 @@ def delete_device(self, blivet_device, delete_parents): actions.extend(result.actions) # for btrfs volumes delete parents partition after deleting volume - if blivet_device.type in ("btrfs volume", "mdarray", "lvmvg") and delete_parents: + if blivet_device.type in ("btrfs volume", "mdarray", "lvmvg", "stratis pool") and delete_parents: for parent in blivet_device.parents: result = self.delete_device(parent, delete_parents=False) @@ -906,7 +922,11 @@ def _pick_device_name(self, name, parent_device=None, snapshot=False): if parent_device: # parent name is part of the child name only on LVM if parent_device.type == "lvmvg": - name = self.storage.suggest_device_name(parent=parent_device, swap=False) + name = self.storage.suggest_device_name(parent=parent_device, swap=False, + device_type=blivet.devicefactory.DEVICE_TYPE_LVM) + elif parent_device.type == "stratis pool": + name = self.storage.suggest_device_name(parent=parent_device, swap=False, + device_type=blivet.devicefactory.DEVICE_TYPE_STRATIS) else: name = self.storage.suggest_device_name(swap=False) elif snapshot: @@ -915,15 +935,23 @@ def _pick_device_name(self, name, parent_device=None, snapshot=False): name = self.storage.suggest_container_name() else: + if not parent_device: + full_name = name + else: + if parent_device.type == "stratis pool": + full_name = "%s/%s" % (parent_device.name, name) + else: + full_name = "%s-%s" % (parent_device.name, name) # if name exists add -XX suffix - if name in self.storage.names or (parent_device and parent_device.name + "-" + name in self.storage.names): + if full_name in self.storage.names: for i in range(100): - if name + "-" + str(i) not in self.storage.names: + if full_name + "-" + str(i) not in self.storage.names: name = name + "-" + str(i) + full_name = full_name + "-" + str(i) break # if still exists let blivet pick it - if name in self.storage.names: + if full_name in self.storage.names: name = self._pick_device_name(name=None, parent_device=parent_device) return name @@ -1313,6 +1341,50 @@ def _create_btrfs_subvolume(self, user_input): return actions + def _create_stratis_pool(self, user_input): + actions = [] + device_name = self._pick_device_name(user_input.name) + + for parent in user_input.size_selection.parents: + # _create_partition needs user_input but we actually don't have it for individual + # parent partitions so we need to 'create' it + size_selection = ProxyDataContainer(total_size=parent.selected_size, parents=[parent]) + part_input = ProxyDataContainer(size_selection=size_selection, + filesystem="stratis", + encrypt=False, + label=None, + mountpoint=None) + part_actions = self._create_partition(part_input) + + # we need to try to create partitions immediately, if something + # fails, fail now + for ac in part_actions: + self.storage.devicetree.actions.add(ac) + actions.extend(part_actions) + + stratis_parents = [ac.device for ac in actions if (ac.is_format and ac.is_create) and ac._format.type == "stratis"] + new_pool = StratisPoolDevice(device_name, + parents=stratis_parents, + encrypted=user_input.encrypt, + passphrase=user_input.passphrase) + actions.append(blivet.deviceaction.ActionCreateDevice(new_pool)) + + return actions + + def _create_stratis_filesystem(self, user_input): + actions = [] + device_name = self._pick_device_name(user_input.name, + user_input.size_selection.parents[0].parent_device) + + new_filesystem = StratisFilesystemDevice(device_name, + parents=[i.parent_device for i in user_input.size_selection.parents], + size=user_input.size_selection.total_size) + new_filesystem.format = blivet.formats.get_format("stratis xfs", mountpoint=user_input.mountpoint) + actions.append(blivet.deviceaction.ActionCreateDevice(new_filesystem)) + actions.append(blivet.deviceaction.ActionCreateFormat(new_filesystem)) + + return actions + add_dict = {"partition": _create_partition, "lvm": _create_lvm, "lvmlv": _create_lvmlv, @@ -1324,7 +1396,9 @@ def _create_btrfs_subvolume(self, user_input): "btrfs subvolume": _create_btrfs_subvolume, "mdraid": _create_mdraid, "lvm snapshot": _create_snapshot, - "lvm thinsnapshot": _create_snapshot} + "lvm thinsnapshot": _create_snapshot, + "stratis pool": _create_stratis_pool, + "stratis filesystem": _create_stratis_filesystem} def add_device(self, user_input): """ Create new device @@ -1486,7 +1560,18 @@ def create_disk_label(self, blivet_device, label_type): return ProxyDataContainer(success=True, actions=actions, message=None, exception=None, traceback=None) - def luks_decrypt(self, blivet_device, passphrase): + def unlock_device(self, blivet_device, passphrase): + """ Unlock/open this LUKS/dm-crypt encrypted device + """ + + if blivet_device.format.type == "luks": + return self._luks_unlock(blivet_device, passphrase) + elif blivet_device.format.type == "stratis": + return self._stratis_unlock(blivet_device, passphrase) + else: + return False + + def _luks_unlock(self, blivet_device, passphrase): """ Decrypt selected luks device :param blivet_device: device to decrypt @@ -1517,6 +1602,30 @@ def luks_decrypt(self, blivet_device, passphrase): self.storage.devicetree.populate() return True + def _stratis_unlock(self, blivet_device, passphrase): + """ Unlock Stratis pool on this device + + :param blivet_device: stratis blockdev with a locked pool + :type blivet_device: StorageDevice + :param passphrase: passphrase + :type passphrase: str + + """ + + log_msg = "Opening Stratis device '%s':\n" % blivet_device + log_utils_call(log=self.log, message=log_msg, + user_input={"device": blivet_device}) + + blivet_device.format.passphrase = passphrase + + try: + blivet_device.format.unlock_pool() + except blivet.errors.StratisError: + return False + else: + self.storage.devicetree.populate() + return True + def blivet_cancel_actions(self, actions): """ Cancel scheduled actions """ diff --git a/blivetgui/blivetgui.py b/blivetgui/blivetgui.py index ae0b3be5..cf98d342 100644 --- a/blivetgui/blivetgui.py +++ b/blivetgui/blivetgui.py @@ -267,7 +267,7 @@ def _raise_exception(self, exception, traceback): raise exception.with_traceback(traceback) def switch_device_view(self, device): - if not (device.is_disk or device.type in ("lvmvg", "btrfs volume", "mdarray")): + if not (device.is_disk or device.type in ("lvmvg", "btrfs volume", "mdarray", "stratis pool")): raise ValueError self.list_devices.select_device_by_name(device.name) @@ -529,7 +529,7 @@ def add_device(self, _widget=None): def _deletable_parents(self, device): - if device.type not in ("btrfs volume", "mdarray", "lvmvg"): + if device.type not in ("btrfs volume", "mdarray", "lvmvg", "stratis pool"): return None deletable_parents = [] @@ -721,7 +721,7 @@ def decrypt_device(self, _widget=None): response = self.run_dialog(dialog) if response: - ret = self.client.remote_call("luks_decrypt", self.list_partitions.selected_partition[0], response) + ret = self.client.remote_call("unlock_device", self.list_partitions.selected_partition[0], response) if not ret: msg = _("Unlocking failed. Are you sure provided password is correct?") diff --git a/blivetgui/dialogs/add_dialog.py b/blivetgui/dialogs/add_dialog.py index 9f0050bd..b3db30e4 100644 --- a/blivetgui/dialogs/add_dialog.py +++ b/blivetgui/dialogs/add_dialog.py @@ -33,6 +33,7 @@ from blivet import size from blivet.devicelibs import crypto, lvm from blivet.formats.fs import BTRFS +from blivet.formats.stratis import StratisBlockdev from ..dialogs import message_dialogs @@ -387,6 +388,9 @@ def _available_add_types(self): if self.selected_free.size > BTRFS._min_size: types.append((_("Btrfs Volume"), "btrfs volume")) + if self.selected_free.size > StratisBlockdev._min_size: + types.append((_("Stratis Pool"), "stratis pool")) + if len([f[0] for f in self.available_free if f[0] == "free"]) > 1: # number of free disk regions types.append((_("Software RAID"), "mdraid")) @@ -409,6 +413,9 @@ def _available_add_types(self): elif self.selected_parent.type in ("btrfs volume", "btrfs subvolume"): types.append((_("Btrfs Subvolume"), "btrfs subvolume")) + elif self.selected_parent.type == "stratis pool": + types.append((_("Stratis Filesystem"), "stratis filesystem")) + return types def add_device_chooser(self): @@ -521,13 +528,17 @@ def update_parent_list(self): self.parents_store.append([fdevice.parents[0], fdevice, False, False, fdevice.parents[0].name, ftype, str(fdevice.size)]) - elif self.selected_type in ("btrfs volume", "lvm", "mdraid"): + elif self.selected_type in ("btrfs volume", "lvm", "mdraid", "stratis pool"): for ftype, fdevice in self.available_free: if ftype == "free": if self.selected_type == "btrfs volume" and fdevice.size < BTRFS._min_size: # too small for new btrfs continue + if self.selected_type == "stratis pool" and fdevice.size < StratisBlockdev._min_size: + # too small for new stratis pool + continue + self.parents_store.append([fdevice.disk, fdevice, False, False, fdevice.disk.name, "disk region", str(fdevice.size)]) @@ -597,6 +608,7 @@ def _get_parent_min_size(self): - lv, thinpool (including thin): one extent - lvm: 2 * lvm.LVM_PE_SIZE - btrfs volume: 256 MiB + - stratis pool: 1 GiB - luks: crypto.LUKS_METADATA_SIZE """ @@ -611,6 +623,8 @@ def _get_parent_min_size(self): min_size = self.selected_parent.vg.pe_size elif device_type == "btrfs volume": min_size = BTRFS._min_size + elif device_type == "stratis pool": + min_size = StratisBlockdev._min_size else: min_size = size.Size("1 MiB") @@ -623,7 +637,7 @@ def _get_parent_max_size(self, parent_device, free_size): device_type = self.selected_type - if device_type in ("partition", "lvm", "btrfs volume", "mdraid"): + if device_type in ("partition", "lvm", "btrfs volume", "mdraid", "stratis pool"): # partition or a device we are going to create partition as a parent # --> we need to use disklabel limit disklabel_limit = size.Size(parent_device.format.parted_disk.maxPartitionLength * parent_device.format.sector_size) @@ -722,6 +736,11 @@ def add_size_area(self): else: raid_level = None + if device_type == "stratis filesystem": + overprovisioning = True + else: + overprovisioning = False + min_size_limit = self._get_min_size_limit() max_size_limit = self._get_max_size_limit() parents = self._get_parents() @@ -730,7 +749,8 @@ def add_size_area(self): parents=parents, min_limit=min_size_limit, max_limit=max_size_limit, - raid_type=raid_level) + raid_type=raid_level, + overprovisioning=overprovisioning) self.grid.attach(size_area.frame, 0, 6, 6, 1) @@ -970,6 +990,14 @@ def on_devices_combo_changed(self, _event): self.show_widgets(["name", "size"]) self.hide_widgets(["label", "fs", "encrypt", "advanced", "mdraid", "mountpoint"]) + elif device_type == "stratis pool": + self.show_widgets(["encrypt", "name", "size"]) + self.hide_widgets(["label", "fs", "advanced", "mdraid", "mountpoint"]) + + elif device_type == "stratis filesystem": + self.show_widgets(["name", "mountpoint", "size"]) + self.hide_widgets(["label", "fs", "encrypt", "advanced", "mdraid"]) + # hide "advanced" encryption widgets if encrypt not checked self._encryption_chooser.set_advanced_visible(self._encryption_chooser.encrypt) diff --git a/blivetgui/dialogs/size_chooser.py b/blivetgui/dialogs/size_chooser.py index 01da690c..dd64ceba 100644 --- a/blivetgui/dialogs/size_chooser.py +++ b/blivetgui/dialogs/size_chooser.py @@ -65,7 +65,7 @@ class SizeArea(GUIWidget): name = "size area" glade_file = "size_area.ui" - def __init__(self, device_type, parents, min_limit, max_limit, raid_type): + def __init__(self, device_type, parents, min_limit, max_limit, raid_type, overprovisioning=False): """ :param device_type: type of device we are creating :param parents: list of available/selected parents @@ -89,6 +89,7 @@ def __init__(self, device_type, parents, min_limit, max_limit, raid_type): self._min_size_limit = min_limit self._max_size_limit = max_limit + self._overprovisioning = overprovisioning # "main" size chooser self.main_chooser = SizeChooser(max_size=self.max_size, min_size=self.min_size) @@ -157,7 +158,10 @@ def max_size(self): parents, raid level and limits for the newly created device """ if self._parent_area is None: - return min(sum(parent.max_size for parent in self.parents), self.max_size_limit) + if self._overprovisioning: + return self.max_size_limit + else: + return min(sum(parent.max_size for parent in self.parents), self.max_size_limit) else: return self._parent_area.total_max @@ -223,10 +227,18 @@ def get_selection(self): them (either specified by user or just fraction of total size) """ if self._parent_area is None: - # no advanced selection -> we will use all available parents and set - # same size for each of them and return total selected size total_size = self.main_chooser.selected_size - parents = self._get_parents_allocation() + + if self._overprovisioning: + # with overprovisioning parent allocation doesn't really make sense + parents = [ParentSelection(parent_device=p.device, + free_space=size.Size(0), + selected_size=total_size) for p in self.parents] + else: + # no advanced selection -> we will use all available parents and set + # same size for each of them and return total selected size + parents = self._get_parents_allocation() + return SizeSelection(total_size=total_size, parents=parents) else: # selection is handled by the parent area diff --git a/blivetgui/list_devices.py b/blivetgui/list_devices.py index 2fd4a795..0a78d415 100644 --- a/blivetgui/list_devices.py +++ b/blivetgui/list_devices.py @@ -116,6 +116,12 @@ def load_group_devices(self): self.device_list.append([device, icon_group, str(device.name + "\n%s" % _("Btrfs Volume"))]) + if gdevices["stratis"]: + self.device_list.append([None, None, "%s" % _("Stratis Pools")]) + for device in gdevices["stratis"]: + self.device_list.append([device, icon_group, + str(device.name + "\n%s" % _("Stratis Pool"))]) + def update_devices_view(self): """ Update device view """ diff --git a/blivetgui/list_parents.py b/blivetgui/list_parents.py index 4288c4ef..076a593e 100644 --- a/blivetgui/list_parents.py +++ b/blivetgui/list_parents.py @@ -72,5 +72,7 @@ def _get_parent_devices(self, device): parents.append(pv) elif device.type in ("btrfs volume", "mdarray"): return device.members + elif device.type == "stratis pool": + return device.blockdevs return parents diff --git a/blivetgui/list_partitions.py b/blivetgui/list_partitions.py index 9dd70b78..23691a6c 100644 --- a/blivetgui/list_partitions.py +++ b/blivetgui/list_partitions.py @@ -86,14 +86,14 @@ def _add_chilren(childs, parent_iter=None): self._add_to_store(logical, child_iter) # lvmvg always has some children, at least a free space - elif selected_device.type == "lvmvg": + elif selected_device.type in ("lvmvg", "stratis pool"): childs = self.blivet_gui.client.remote_call("get_children", selected_device) _add_chilren(childs, None) # for btrfs volumes and mdarrays its necessary to add the device itself to the view # because these devices don't need to have children (only btrfs volume or only mdarray # is a valid, usable device) - elif selected_device.type == "btrfs volume" or (selected_device.type == "mdarray" and not selected_device.children): + elif selected_device.type in ("btrfs volume",) or (selected_device.type == "mdarray" and not selected_device.children): parent_iter = self._add_to_store(selected_device) childs = self.blivet_gui.client.remote_call("get_children", selected_device) _add_chilren(childs, parent_iter) @@ -109,16 +109,16 @@ def _add_chilren(childs, parent_iter=None): def _is_group_device(self, blivet_device): # btrfs volume on raw disk - if blivet_device.type in ("btrfs volume", "lvmvg"): + if blivet_device.type in ("btrfs volume", "lvmvg", "stratis pool"): return True - if blivet_device.format and blivet_device.format.type in ("lvmpv", "btrfs", "mdmember"): + if blivet_device.format and blivet_device.format.type in ("lvmpv", "btrfs", "mdmember", "stratis"): return (len(blivet_device.children) > 0) # encrypted group device if blivet_device.format and blivet_device.format.type in ("luks", "integrity") and blivet_device.children: luks_device = self.blivet_gui.client.remote_call("get_luks_device", blivet_device) - if luks_device.format and luks_device.format.type in ("lvmpv", "btrfs", "mdmember"): + if luks_device.format and luks_device.format.type in ("lvmpv", "btrfs", "mdmember", "stratis"): return (len(luks_device.children) > 0) return False @@ -163,7 +163,7 @@ def _add_to_store(self, device, parent_iter=None): return device_iter def _allow_recursive_delete_device(self, device): - if device.type not in ("btrfs volume", "mdarray", "lvmvg"): + if device.type not in ("btrfs volume", "mdarray", "lvmvg", "stratis pool"): return False def _device_descendants(device): @@ -223,7 +223,7 @@ def _allow_format_device(self, device): if device.type == "partition" and device.is_extended: return False - if device.format.type in ("mdmember", "btrfs"): + if device.format.type in ("mdmember", "btrfs", "stratis"): return False return not device.format.status @@ -269,7 +269,8 @@ def _allow_add_device(self, device): if device.protected: return False - if device.type in ("free space", "btrfs volume", "btrfs subvolume", "lvmthinpool"): + if device.type in ("free space", "btrfs volume", "btrfs subvolume", "lvmthinpool", + "stratis pool"): return True # empty lvmpv @@ -328,7 +329,8 @@ def activate_action_buttons(self, selected_device): if device.format: if device.format.type == "luks" and not device.format.status and device.format.exists: self.blivet_gui.activate_device_actions(["decrypt"]) - + elif device.format.type == "stratis" and device.format.locked_pool and not device.children: + self.blivet_gui.activate_device_actions(["decrypt"]) elif device.format.mountable and device.format.system_mountpoint: self.blivet_gui.activate_device_actions(["unmount"]) diff --git a/blivetgui/visualization/logical_view.py b/blivetgui/visualization/logical_view.py index 7b2c2f66..f96c2880 100644 --- a/blivetgui/visualization/logical_view.py +++ b/blivetgui/visualization/logical_view.py @@ -260,5 +260,5 @@ def _on_button_release(self, button, event): def _on_button_press(self, button, event): if event.type == Gdk.EventType._2BUTTON_PRESS: - if button.device.is_disk or button.device.type in ("lvmvg", "btrfs volume", "mdarray"): + if button.device.is_disk or button.device.type in ("lvmvg", "btrfs volume", "mdarray", "stratis pool"): self.blivet_gui.switch_device_view(button.device) diff --git a/blivetgui/visualization/rectangle.py b/blivetgui/visualization/rectangle.py index a6f1a1c1..c9cfc755 100644 --- a/blivetgui/visualization/rectangle.py +++ b/blivetgui/visualization/rectangle.py @@ -81,7 +81,7 @@ def _add_device_icons(self): def _get_device_properties(self): properties = [] - if self.device.type in ("lvmvg", "btrfs volume", "mdarray"): + if self.device.type in ("lvmvg", "btrfs volume", "mdarray", "stratis pool"): properties.append("group") if self.device.format and self.device.format.type in ("iso9660", "udf"): properties.append("livecd") diff --git a/tests/blivetgui_tests/add_dialog_test.py b/tests/blivetgui_tests/add_dialog_test.py index 45b2eccf..060023a7 100644 --- a/tests/blivetgui_tests/add_dialog_test.py +++ b/tests/blivetgui_tests/add_dialog_test.py @@ -288,7 +288,7 @@ def test_allowed_device_types(self): types = sorted([i[1] for i in add_dialog.devices_combo.get_model()]) - self.assertTrue(sorted(["partition", "lvm", "btrfs volume", "mdraid"]) == types) + self.assertTrue(sorted(["partition", "lvm", "btrfs volume", "mdraid", "stratis pool"]) == types) self.assertTrue(add_dialog.devices_combo.get_sensitive()) # disk with disklabel and not enough free space, no other disks available @@ -399,6 +399,24 @@ def test_mdraid_widgets(self): self.assertIsNotNone(add_dialog.advanced) self.assertFalse(add_dialog.md_type_combo.get_visible()) + def test_stratis_pool_widgets(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)], self.supported_filesystems, []) + + add_dialog.devices_combo.set_active_id("stratis pool") + self.assertEqual(add_dialog.selected_type, "stratis pool") + + self.assertFalse(add_dialog.filesystems_combo.get_visible()) + self.assertTrue(add_dialog.name_entry.get_visible()) + self.assertTrue(add_dialog._encryption_chooser._encrypt_check.get_visible()) + self.assertFalse(add_dialog._raid_chooser.get_visible()) + self.assertIsNone(add_dialog.advanced) + self.assertFalse(add_dialog.md_type_combo.get_visible()) + self.assertTrue(add_dialog.size_area.get_sensitive()) + def test_partition_parents(self): parent_device = self._get_parent_device() free_device = self._get_free_device(parent=parent_device) @@ -839,6 +857,34 @@ def test_btrfs_selection(self, *args): # pylint: disable=unused-argument,argume self.assertEqual(selection.size_selection.parents[0].selected_size, free_device.size) self.assertEqual(selection.raid_level, "single") + def test_stratis_selection(self): + parent_device = self._get_parent_device() + free_device = self._get_free_device(parent=parent_device, size=Size("8 GiB"), is_free_region=False, + is_empty_disk=True) + + add_dialog = AddDialog(self.parent_window, parent_device, free_device, + [("free", free_device)], self.supported_filesystems, []) + + add_dialog.devices_combo.set_active_id("stratis pool") + + name = "name" + + add_dialog.name_entry.set_text(name) + + selection = add_dialog.get_selection() + + self.assertEqual(selection.device_type, "stratis pool") + self.assertEqual(selection.size_selection.total_size, free_device.size) + self.assertTrue(selection.filesystem in (None, "")) + self.assertEqual(selection.name, name) + self.assertTrue(selection.label in (None, "")) + self.assertTrue(selection.mountpoint in (None, "")) + self.assertFalse(selection.encrypt) + self.assertTrue(selection.passphrase in (None, "")) + self.assertEqual(selection.size_selection.parents[0].parent_device, parent_device) + self.assertEqual(selection.size_selection.parents[0].selected_size, free_device.size) + self.assertTrue(selection.raid_level in (None, "")) + def test_parents_max_size_limit(self): parent_device1 = self._get_parent_device(size=Size("8 TiB")) free_device1 = self._get_free_device(parent=parent_device1, size=parent_device1.size) diff --git a/tests/blivetgui_tests/size_widgets_test.py b/tests/blivetgui_tests/size_widgets_test.py index 6659c4b3..f6e61e02 100644 --- a/tests/blivetgui_tests/size_widgets_test.py +++ b/tests/blivetgui_tests/size_widgets_test.py @@ -573,6 +573,28 @@ def test_70_parent_allocation(self): selected_sizes = [r.selected_size for r in ret] self.assertListEqual(selected_sizes, [Size(1), Size(2)]) + def test_75_parent_allocation_overprovisioning(self): + """ Test allocating size on parents without ParentArea with overprovisioning """ + + # -- same size parents + parents = [MagicMock(device=self._mock_device(), min_size=Size("1 MiB"), max_size=Size("1 GiB"), + reserved_size=Size(0)), + MagicMock(device=self._mock_device(), min_size=Size("1 MiB"), max_size=Size("1 GiB"), + reserved_size=Size(0))] + + size_area = SizeArea(device_type="lvm", parents=parents, + min_limit=Size(1), max_limit=Size("200 GiB"), + raid_type=None, overprovisioning=True) + + # select maximum (bigger than parents) --> both parents should have max_limit selected + size_area.main_chooser.selected_size = Size("200 GiB") + ret = size_area.get_selection() + self.assertEqual(len(ret.parents), 2) + self.assertEqual(ret.parents[0].parent_device, parents[0].device) + self.assertEqual(ret.parents[0].selected_size, Size("200 GiB")) + self.assertEqual(ret.parents[1].parent_device, parents[1].device) + self.assertEqual(ret.parents[1].selected_size, Size("200 GiB")) + @unittest.skipUnless("DISPLAY" in os.environ.keys(), "requires X server") class ParentAreaTest(unittest.TestCase): diff --git a/tests/blivetutils_tests/test_10_disks.py b/tests/blivetutils_tests/test_10_disks.py index 70f96472..f7c31994 100644 --- a/tests/blivetutils_tests/test_10_disks.py +++ b/tests/blivetutils_tests/test_10_disks.py @@ -39,7 +39,7 @@ class BlivetUtilsDisksTest(BlivetUtilsTestCase, DisksTestToolkit): def test_10_empty_disks(self): # all disks are empty --> no "group" devices group_devices = self.blivet_utils.get_group_devices() - self.assertDictEqual(group_devices, {"lvm": [], "raid": [], "btrfs": []}) + self.assertDictEqual(group_devices, {"lvm": [], "raid": [], "btrfs": [], "stratis": []}) # disks are empty and without partition table --> no usable free space # should be reported (unpartitioned disks are not considered usable)