def _get_min_size_limit(self): limit = size.Size(0) if self.selected_fs: limit = self.selected_fs._min_size return limit or size.Size("1 MiB")
def get_selection(self): if self.device_type in ("lvm", "lvmvg"): return {"pesize": size.Size(self.pesize_combo.get_active_text())} elif self.device_type == "partition": return {"parttype": self.partition_combo.get_active_id()} elif self.device_type == "mdraid": return {"chunk_size": size.Size(self.chunk_combo.get_active_text())}
def _get_min_size_limit(self): limit = size.Size(0) if self.selected_fs: limit = self.selected_fs._min_size parent_limit = self._get_parent_min_size() limit = max(limit, parent_limit) return limit or size.Size("1 MiB")
def default_unit(self): """ Default, preselected unit -- GiB for devices larger that 5 GiB, otherwise the biggest available unit """ dev_size = self.max_size - self.min_size if dev_size >= size.Size("5 GiB"): return size.GiB elif dev_size >= size.Size("5 MiB"): return size.MiB else: return self.available_units[-1]
def add_device_chooser(self): map_type_devices = { "disk" : [(_("Partition"), "partition"), (_("LVM2 Storage"), "lvm"), (_("LVM2 Physical Volume"), "lvmpv")], "lvmpv" : [(_("LVM2 Volume Group"), "lvmvg")], "lvmvg" : [(_("LVM2 Logical Volume"), "lvmlv")], "luks/dm-crypt" : [(_("LVM2 Volume Group"), "lvmvg")], "mdarray" : [(_("LVM2 Volume Group"), "lvmvg")], "btrfs volume" : [(_("Btrfs Subvolume"), "btrfs subvolume")] } label_devices = Gtk.Label(label=_("Device type:"), xalign=1) label_devices.get_style_context().add_class("dim-label") self.grid.attach(label_devices, 0, 0, 1, 1) if self.device_type == "disk" and self.free_device.isLogical: devices = [(_("Partition"), "partition"), (_("LVM2 Storage"), "lvm"), (_("LVM2 Physical Volume"), "lvmpv")] elif self.device_type == "disk" and not self.parent_device.format.type \ and self.free_device.size > size.Size("256 MiB"): devices = [(_("Btrfs Volume"), "btrfs volume")] else: devices = map_type_devices[self.device_type] if self.device_type == "disk" and len(self.free_disks_regions) > 1: devices.append((_("Software RAID"), "mdraid")) if self.device_type == "disk" and self.free_device.size > size.Size("256 MiB"): devices.append((_("Btrfs Volume"), "btrfs volume")) devices_store = Gtk.ListStore(str, str) for device in devices: devices_store.append([device[0], device[1]]) devices_combo = Gtk.ComboBox.new_with_model(devices_store) devices_combo.set_entry_text_column(0) if len(devices) == 1: devices_combo.set_sensitive(False) self.grid.attach(devices_combo, 1, 0, 2, 1) renderer_text = Gtk.CellRendererText() devices_combo.pack_start(renderer_text, True) devices_combo.add_attribute(renderer_text, "text", 0) return devices_combo
def _scale_precision(self, unit): """ Get number of decimal places to be displayed for selected unit and step for the scale. We should allow one decimal place for GB and bigger (step 0.1) and no decimal values for MiB and smaller (step 1). :param unit: selected size unit :type unit: size unit constant (e.g. blivet.size.KiB) """ if size.Size("1 " + size.unit_str(unit)) >= size.Size("1 GB"): return (1, 0.1) else: return (0, 1)
def selected(self, status): self._selected = status # mark the button as (not) selected if self.checkbutton_use.get_active() != status: self.checkbutton_use.set_active(status) if status: self.size_chooser.set_sensitive(True) self.size_chooser.min_size = self.min_size self.selected_size = self.max_size else: self.size_chooser.set_sensitive(False) self.size_chooser.min_size = size.Size(0) self.selected_size = size.Size(0)
def validate_user_input(self): if self.device_type == "mdraid": try: chunk_size = size.Size(self.chunk_combo.get_active_text()) except ValueError: msg = _("'{0}' is not a valid chunk size specification.").format(self.chunk_combo.get_active_text()) message_dialogs.ErrorDialog(self.add_dialog, msg, not self.add_dialog.installer_mode) # do not show decoration in installer mode return False if chunk_size % size.Size("4 KiB") != size.Size(0): msg = _("Chunk size must be multiple of 4 KiB.") message_dialogs.ErrorDialog(self.add_dialog, msg, not self.add_dialog.installer_mode) # do not show decoration in installer mode return False return True
def available_units(self): """ Units that should be available to select in this chooser -- depends on size of the device, e.g. TiB will be available only for devices bigger than 2 TiB """ units = [] dev_size = (self.max_size - self.min_size) or self.max_size if dev_size < size.Size("2 B"): return [size.B] for unit in UNITS.keys(): if size.Size("2 " + unit) <= dev_size: units.append(UNITS[unit]) return units
def _get_parent_min_size(self): """ Get minimal size for parent devices of newly created device. This value depends on type of created device. - partition: no limit - lv, thinpool (including thin): one extent - lvm: 2 * lvm.LVM_PE_SIZE - btrfs volume: 256 MiB - luks: crypto.LUKS_METADATA_SIZE """ device_type = self.selected_type if device_type in ("lvmlv", "lvmthinpool"): min_size = self.selected_parent.pe_size elif device_type == "lvm": min_size = lvm.LVM_PE_SIZE * 2 elif device_type in ("lvmthinlv", "lvm snapshot"): min_size = self.selected_parent.vg.pe_size elif device_type == "btrfs volume": min_size = BTRFS._min_size else: min_size = size.Size("1 MiB") return min_size
def on_encrypt_check(self, _toggle): if self.encrypt_check.get_active(): self.show_widgets(["passphrase"]) self.update_size_area_limits(reserved_size=crypto.LUKS_METADATA_SIZE) else: self.hide_widgets(["passphrase"]) self.update_size_area_limits(reserved_size=size.Size(0))
def on_encrypt_check(self, _toggle): if self._encryption_chooser.encrypt: self.update_size_area_limits(min_size=self._get_min_size_limit(), reserved_size=crypto.LUKS_METADATA_SIZE) else: self.update_size_area_limits(min_size=self._get_min_size_limit(), reserved_size=size.Size(0))
def _get_parents_allocation(self): """ Without advanced area we need to choose how much space to use on each parent """ total_size = self.main_chooser.selected_size res = [] unallocated_parents = self.parents[:] allocated_size = size.Size(0) while allocated_size < total_size: smallest_parent = min([p for p in unallocated_parents], key=lambda x: x.max_size) if (smallest_parent.max_size * len(unallocated_parents)) >= (total_size - allocated_size): # just put remaining size / number of remaining parents to each parent for parent in unallocated_parents: res.append( ParentSelection( parent_device=parent.device, free_space=parent.free_space, selected_size=(total_size - allocated_size) // len(unallocated_parents))) allocated_size += ((total_size - allocated_size) // len(unallocated_parents)) unallocated_parents.remove(parent) else: # use entire smallest remaining parent res.append( ParentSelection(parent_device=smallest_parent.device, free_space=smallest_parent.free_space, selected_size=smallest_parent.max_size)) allocated_size += smallest_parent.max_size unallocated_parents.remove(smallest_parent) return res
def _on_unit_changed(self, combo): """ On-change action for unit combo """ new_unit = UNITS[combo.get_active_text()] old_unit = self.selected_unit self.selected_unit = new_unit selected_size = size.Size(str(self._scale.get_value()) + " " + size.unit_str(old_unit)) self._reset_size_widgets(selected_size) for handler in self._unit_change_handlers: handler.method(self.selected_unit, *handler.args)
def total_size(self): """ Total size selected in this area """ total_size = size.Size(0) # for raids, total size must be calculated separately if self.raid_type not in (Linear, Single, None): total_size = self.raid_type.get_net_array_size(len(self.selected_choosers), min([ch.selected_size for ch in self.selected_choosers])) else: for chooser in self.choosers: total_size += chooser.selected_size return total_size
def convert_to_size(self, size_num, unit): """ Convert floats from scale to Size .. note:: Neccesary for floats in form 1e-10 """ str_size = str(size_num) if "e" in str_size: exp = abs(int(str_size.split("e")[-1])) dec = len(str_size.split("e")[0].split(".")[-1]) str_size = format(size, "." + str(exp+dec) + "f") return size.Size(str_size + unit)
def _get_parent_max_size(self, parent_device, free_size): """ Get maximal size for parent devices of newly created device. This value depends on type of created device. """ device_type = self.selected_type if device_type in ("partition", "lvm", "btrfs volume", "mdraid"): # 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) max_size = min(disklabel_limit, free_size) else: max_size = free_size return max_size
def _get_parents(self): """ Get selected parents for newly created device """ parents = [] # for encrypted parents add space for luks metada if self.encrypt_check.get_active(): reserved_size = crypto.LUKS_METADATA_SIZE else: reserved_size = size.Size(0) if self.selected_parent.type == "lvmvg": if self.selected_type == "lvmthinpool": free = self.selected_free.size * POOL_RESERVED else: free = self.selected_free.size parent = ProxyDataContainer(device=self.selected_parent, free_space=self.selected_free, min_size=self._get_parent_min_size(), max_size=self._get_parent_max_size( self.selected_parent, free), reserved_size=reserved_size) parents.append(parent) else: for row in self.parents_store: if row[3]: parent = ProxyDataContainer( device=row[0], free_space=row[1], min_size=self._get_parent_min_size(), max_size=self._get_parent_max_size( row[0], row[1].size), reserved_size=reserved_size) parents.append(parent) if not parents: # FIXME parent = ProxyDataContainer(device=self.selected_parent, free_space=self.selected_free, min_size=self._get_parent_min_size(), max_size=self._get_parent_max_size( self.selected_parent, self.selected_free.size), reserved_size=reserved_size) parents.append(parent) return parents
def _get_max_size_limit(self): limit = size.Size("16 EiB") if self.selected_fs: # some filesystems have 0 max size, so use 'our' upper limit for them limit = min(self.selected_fs._max_size, limit) or limit # XXX: free space for LVs is calculated based on free space on the PVs # but newly allocated LVs doesn't decrease this space, so we need some # way how to limit maximum size of the new LV if self.selected_type == "lvmlv": limit = min(self.selected_parent.free_space, limit) # same applies to thinpools, but we need to use another hack to limit # it's max size and leave some free space in the VG elif self.selected_type == "lvmthinpool": limit = min(self.selected_parent.free_space * POOL_RESERVED, limit) return limit
def lvm_options(self): label_pesize = Gtk.Label(label=_("PE Size:"), xalign=1) self.grid.attach(label_pesize, 0, 0, 1, 1) pesize_combo = Gtk.ComboBoxText() pesize_combo.set_entry_text_column(0) pesize_combo.set_id_column(0) for pesize in SUPPORTED_PESIZE: if (2 * size.Size(pesize)) > self.free_device.size: # we need at least two free extents in the vg break pesize_combo.append_text(pesize) pesize_combo.connect("changed", self.on_pesize_changed) pesize_combo.set_active_id("4 MiB") self.grid.attach(pesize_combo, 1, 0, 2, 1) self.widgets.extend([label_pesize, pesize_combo]) return pesize_combo
def selected_size(self): return size.Size( str(self._scale.get_value()) + " " + size.unit_str(self.selected_unit))
def add_size_areas(self): device_type = self._get_selected_device_type() self.widgets_dict["size"] = [] if self.size_areas: for area in self.size_areas: area.destroy() self.size_scroll.destroy() self.size_grid.destroy() self.size_areas = [] size_scroll = Gtk.ScrolledWindow() size_scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER) self.grid.attach(size_scroll, 0, 6, 6, 1) size_scroll.show() size_grid = Gtk.Grid(column_homogeneous=False, row_spacing=10, column_spacing=5) size_scroll.add(size_grid) size_grid.show() posititon = 0 raid, max_size = self.raid_member_max_size() min_size = size.Size("1 MiB") if device_type in ("lvmpv", "lvm"): min_size = size.Size("8 MiB") elif device_type == "btrfs volume": min_size = size.Size("256 MiB") for row in self.parents_store: if row[3]: if not raid: max_size = row[1].size area = SizeChooserArea(dialog=self, parent_device=row[0], free_device=row[1], max_size=max_size, min_size=min_size, dialog_type="add") size_grid.attach(area.frame, 0, posititon, 1, 1) self.widgets_dict["size"].append(area) self.size_areas.append(area) posititon += 1 for area in self.size_areas: area.show() if device_type in ("lvmvg", "btrfs subvolume"): area.set_sensitive(False) size_area_height = size_grid.size_request().height size_area_width = size_grid.size_request().width screen_height = Gdk.Screen.get_default().get_height() screen_width = Gdk.Screen.get_default().get_width() dialog_height = self.size_request().height size_diff = int((screen_height*0.7) - dialog_height) if size_diff < 0: # dialog is largen than 70 % of screen areas_to_display = len(self.size_areas) - (abs(size_diff) / (size_area_height / len(self.size_areas))) if areas_to_display < 1: size_scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) else: if size_area_height > screen_width*0.7: size_scroll.set_size_request(screen_width*0.7, int(size_area_height/len(self.size_areas))*areas_to_display) size_scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) else: size_scroll.set_size_request(size_area_width, int(size_area_height/len(self.size_areas))*areas_to_display) size_scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) else: if size_area_width > screen_width*0.7: size_scroll.set_size_request(screen_width*0.7, size_area_height) size_scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER) else: size_grid.set_size_request(size_area_width, size_area_height + 20) size_scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER) return size_grid, size_scroll
def on_pesize_changed(self, combo): pesize = combo.get_active_id() min_size = size.Size(pesize) * 2 self.add_dialog.update_size_area_limits(min_size=min_size)