Patch 5 adds support for specifying the names of lvs and mds.
The rest are little improvements, tweaks, and bug fixes.
It should be done by modifying the VG via the RHS. --- pyanaconda/ui/gui/spokes/custom.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index f9b0694..39327c1 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -1919,6 +1919,10 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if device.exists: return
+ if self._get_current_device_type() == DEVICE_TYPE_LVM: + # LVM disk set management happens through VG edit on RHS + return + self.clear_errors()
dialog = DisksDialog(self.data,
--- pyanaconda/storage/__init__.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index 9685ec0..e480739 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -1867,6 +1867,11 @@ class Storage(object): # new container, so use the factory's disk set add_disks = factory.disks
+ # drop any new disks that don't have free space + min_free = min(500, factory.size) + add_disks = [d for d in add_disks if d.partitioned and + d.format.free >= min_free] + base_size = max(1, getFormat(factory.member_format).minSize)
# XXX TODO: multiple member devices per disk
When editing a non-lv and changing the device type type to lvm it is possible that there are no vg instances in the devicetree. --- pyanaconda/ui/gui/spokes/custom.py | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 39327c1..29643bf 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -2222,6 +2222,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): container = self.__storage.getContainer(factory) default_vg = getattr(container, "name", None)
+ log.debug("default vg is %s" % default_vg) vg_combo.remove_all() vgs = self.__storage.vgs for vg in vgs: @@ -2229,9 +2230,15 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if default_vg and vg.name == default_vg: vg_combo.set_active(vgs.index(vg))
+ if default_vg is None: + hostname = self.data.network.hostname + default_vg = self.__storage.suggestContainerName(hostname=hostname) + vg_combo.append_text(default_vg) + vg_combo.set_active(len(vg_combo.get_model()) - 1) + vg_combo.append_text(new_vg_text) if default_vg is None: - vg_combo.set_active(len(vg_combo.get_model())) + vg_combo.set_active(len(vg_combo.get_model()) - 1)
vg_combo.show() vg_button.show()
On Thu, Nov 29, 2012 at 11:19:27AM -0600, David Lehman wrote:
When editing a non-lv and changing the device type type to lvm it is possible that there are no vg instances in the devicetree.
pyanaconda/ui/gui/spokes/custom.py | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 39327c1..29643bf 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -2222,6 +2222,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): container = self.__storage.getContainer(factory) default_vg = getattr(container, "name", None)
log.debug("default vg is %s" % default_vg) vg_combo.remove_all() vgs = self.__storage.vgs for vg in vgs:
@@ -2229,9 +2230,15 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if default_vg and vg.name == default_vg: vg_combo.set_active(vgs.index(vg))
if default_vg is None:
hostname = self.data.network.hostname
default_vg = self.__storage.suggestContainerName(hostname=hostname)
vg_combo.append_text(default_vg)
vg_combo.set_active(len(vg_combo.get_model()) - 1)
vg_combo.append_text(new_vg_text) if default_vg is None:
vg_combo.set_active(len(vg_combo.get_model()))
vg_combo.set_active(len(vg_combo.get_model()) - 1) vg_combo.show() vg_button.show()
-- 1.7.7.6
Does this depend on some other patches? On master custom.py doesn't have default_vg code in it. And it ends at line 2079...
On Thu, 2012-11-29 at 14:31 -0800, Brian C. Lane wrote:
On Thu, Nov 29, 2012 at 11:19:27AM -0600, David Lehman wrote:
When editing a non-lv and changing the device type type to lvm it is possible that there are no vg instances in the devicetree.
pyanaconda/ui/gui/spokes/custom.py | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 39327c1..29643bf 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -2222,6 +2222,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): container = self.__storage.getContainer(factory) default_vg = getattr(container, "name", None)
log.debug("default vg is %s" % default_vg) vg_combo.remove_all() vgs = self.__storage.vgs for vg in vgs:
@@ -2229,9 +2230,15 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if default_vg and vg.name == default_vg: vg_combo.set_active(vgs.index(vg))
if default_vg is None:
hostname = self.data.network.hostname
default_vg = self.__storage.suggestContainerName(hostname=hostname)
vg_combo.append_text(default_vg)
vg_combo.set_active(len(vg_combo.get_model()) - 1)
vg_combo.append_text(new_vg_text) if default_vg is None:
vg_combo.set_active(len(vg_combo.get_model()))
vg_combo.set_active(len(vg_combo.get_model()) - 1) vg_combo.show() vg_button.show()
-- 1.7.7.6
Does this depend on some other patches? On master custom.py doesn't have default_vg code in it. And it ends at line 2079...
Yeah, it's on top of my last set of four, which I didn't want to push without this patch. The patch was 2/4 from that set (Add support for changing a new LV's VG).
--- pyanaconda/ui/gui/spokes/custom.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 29643bf..8a6c539 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -1395,6 +1395,9 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): base_size = factory.device_size except MDRaidError as e: log.error("failed to populate UI raid options: %s" % e) + self._error = e + self.window.set_info(Gtk.MessageType.WARNING, str(e)) + self.window.show_all() return
active = raid_level_features[raid_level] @@ -1946,6 +1949,8 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): return
self._device_disks = disks + self._populate_raid(self._get_raid_level(), + self.builder.get_object("sizeSpinner").get_value())
def run_vg_editor(self, vg=None, name=None): if vg:
On Thu, Nov 29, 2012 at 11:19:28AM -0600, David Lehman wrote:
pyanaconda/ui/gui/spokes/custom.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 29643bf..8a6c539 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -1395,6 +1395,9 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): base_size = factory.device_size except MDRaidError as e: log.error("failed to populate UI raid options: %s" % e)
self._error = e
self.window.set_info(Gtk.MessageType.WARNING, str(e))
self.window.show_all() return
This can use clumens' new self.set_warning() code.
On Thu, 2012-11-29 at 14:33 -0800, Brian C. Lane wrote:
On Thu, Nov 29, 2012 at 11:19:28AM -0600, David Lehman wrote:
pyanaconda/ui/gui/spokes/custom.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 29643bf..8a6c539 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -1395,6 +1395,9 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): base_size = factory.device_size except MDRaidError as e: log.error("failed to populate UI raid options: %s" % e)
self._error = e
self.window.set_info(Gtk.MessageType.WARNING, str(e))
self.window.show_all() return
This can use clumens' new self.set_warning() code.
I wrote it to use that but, since it hadn't been pushed when I was testing, I used the old way. Then I promptly forgot all about changing it back. Thanks for reminding me.
anaconda-patches mailing list anaconda-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
--- pyanaconda/storage/__init__.py | 2 +- pyanaconda/ui/gui/spokes/custom.glade | 48 ++++++++++++++++++++--- pyanaconda/ui/gui/spokes/custom.py | 69 ++++++++++++++++++++++++++++++-- 3 files changed, 107 insertions(+), 12 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index e480739..3bbdf11 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -2266,7 +2266,7 @@ class Storage(object): mountpoint=mountpoint, fmt_args=fmt_args, **kwa) - except StorageError as e: + except (StorageError, ValueError) as e: log.error("device instance creation failed: %s" % e) _container_post_error() raise diff --git a/pyanaconda/ui/gui/spokes/custom.glade b/pyanaconda/ui/gui/spokes/custom.glade index f4e27eb..182d7a3 100644 --- a/pyanaconda/ui/gui/spokes/custom.glade +++ b/pyanaconda/ui/gui/spokes/custom.glade @@ -488,7 +488,7 @@ you'll be able to view their details here.</property> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">0</property> + <property name="top_attach">1</property> <property name="width">1</property> <property name="height">1</property> </packing> @@ -503,7 +503,7 @@ you'll be able to view their details here.</property> </object> <packing> <property name="left_attach">1</property> - <property name="top_attach">0</property> + <property name="top_attach">1</property> <property name="width">1</property> <property name="height">1</property> </packing> @@ -518,7 +518,7 @@ you'll be able to view their details here.</property> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">1</property> + <property name="top_attach">2</property> <property name="width">1</property> <property name="height">1</property> </packing> @@ -534,7 +534,7 @@ you'll be able to view their details here.</property> </object> <packing> <property name="left_attach">2</property> - <property name="top_attach">1</property> + <property name="top_attach">2</property> <property name="width">1</property> <property name="height">1</property> </packing> @@ -548,7 +548,7 @@ you'll be able to view their details here.</property> </object> <packing> <property name="left_attach">1</property> - <property name="top_attach">1</property> + <property name="top_attach">2</property> <property name="width">1</property> <property name="height">1</property> </packing> @@ -566,12 +566,48 @@ you'll be able to view their details here.</property> </object> <packing> <property name="left_attach">3</property> - <property name="top_attach">1</property> + <property name="top_attach">2</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> + <object class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Name:</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="nameEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> <placeholder/> </child> <child> diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 8a6c539..9241742 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -21,7 +21,7 @@ #
# TODO: -# - Add a way for users to specify the names of md, lv, subvol devices. +# - Add a way for users to specify the names of subvols. # - We should either remove boot disk selection from the cart we show from here # or re-partition when it gets changed to make a best-effort at keeping up. # - Deleting an LV is not reflected in available space in the bottom left. @@ -436,6 +436,11 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
self._device_disks = [] self._device_container_name = None + self._device_name_dict = {DEVICE_TYPE_LVM: None, + DEVICE_TYPE_MD: None, + DEVICE_TYPE_PARTITION: "", + DEVICE_TYPE_BTRFS: "", + DEVICE_TYPE_DISK: ""}
self._initialized = False
@@ -879,9 +884,23 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): if self._partitionsNotebook.get_current_page() != NOTEBOOK_DETAILS_PAGE: return
+ use_dev = device + if device.type == "luks/dm-crypt": + use_dev = device.slave + log.info("ui: saving changes to device %s" % device.name)
# TODO: member type + old_name = getattr(use_dev, "lvname", use_dev.name) + name = old_name + changed_name = False + name_entry = self.builder.get_object("nameEntry") + if name_entry.get_sensitive(): + name = name_entry.get_text() + changed_name = (name != old_name) + + log.debug("old_name: %s" % old_name) + log.debug("new_name: %s" % name)
size = self.builder.get_object("sizeSpinner").get_value() log.debug("new size: %s" % size) @@ -987,9 +1006,6 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): ## ## DEVICE TYPE (early return) ## - use_dev = device - if device.type == "luks/dm-crypt": - use_dev = device.slave current_device_type = getDeviceType(device) old_raid_level = getRAIDLevel(device) changed_device_type = (current_device_type != device_type) @@ -1051,7 +1067,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self._replace_device(device_type, size, fstype=fs_type, disks=disks, mountpoint=mountpoint, label=label, raid_level=raid_level, - encrypted=encrypted, + encrypted=encrypted, name=name, container_name=self._device_container_name, selector=selector) except ErrorRecoveryFailure as e: @@ -1077,6 +1093,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): label=old_label, raid_level=old_raid_level, encrypted=prev_encrypted, + name=old_name, container_name=old_container_name, selector=selector) except StorageError as e: @@ -1170,6 +1187,20 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self._updateSpaceDisplay() self._populate_right_side(selector)
+ + ## + ## NAME + ## + if changed_name: + use_dev._name = name + new_name = use_dev.name + if new_name in self.__storage.names: + use_dev._name = old_name + self.set_info(_("Specified name %s already in use.") % new_name) + else: + if old_name == selector.props.name: + selector.props.name = new_name + if reformat: ## ## ENCRYPTION @@ -1452,6 +1483,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): reformatCheckbox = self.builder.get_object("reformatCheckbox") labelEntry = self.builder.get_object("labelEntry") mountPointEntry = self.builder.get_object("mountPointEntry") + nameEntry = self.builder.get_object("nameEntry") selectedDeviceLabel = self.builder.get_object("selectedDeviceLabel") selectedDeviceDescLabel = self.builder.get_object("selectedDeviceDescLabel") sizeSpinner = self.builder.get_object("sizeSpinner") @@ -1481,6 +1513,9 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): selectedDeviceLabel.set_text(selector.props.name) selectedDeviceDescLabel.set_text(self._description(selector.props.name))
+ device_name = getattr(use_dev, "lvname", use_dev.name) + nameEntry.set_text(device_name) + mountPointEntry.set_text(getattr(device.format, "mountpoint", "") or "") mountPointEntry.set_sensitive(hasattr(device.format, "mountpoint"))
@@ -1631,6 +1666,23 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): DEVICE_TYPE_LVM: lvm_pos, DEVICE_TYPE_MD: md_pos, DEVICE_TYPE_DISK: disk_pos} + + for _type in self._device_name_dict.iterkeys(): + if _type == device_type: + self._device_name_dict[_type] = device_name + continue + elif _type not in (DEVICE_TYPE_LVM, DEVICE_TYPE_MD): + continue + + swap = (device.format.type == "swap") + mountpoint = getattr(device.format, "mountpoint", None) + + with ui_storage_logger(): + name = self.__storage.suggestDeviceName(swap=swap, + mountpoint=mountpoint) + + self._device_name_dict[_type] = name + typeCombo.set_active(type_index_map[device_type])
# you can't change the type of an existing device @@ -1639,6 +1691,9 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self._populate_raid(raid_level, device.size) self._populate_lvm(device=use_dev) self.builder.get_object("optionsNotebook").set_sensitive(not device.exists) + # do this last in case this was set sensitive in on_device_type_changed + if use_dev.exists: + nameEntry.set_sensitive(False)
### ### SIGNAL HANDLERS @@ -2304,6 +2359,10 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self._populate_raid(raid_level, size) self._populate_lvm()
+ nameEntry = self.builder.get_object("nameEntry") + nameEntry.set_sensitive(new_type in (DEVICE_TYPE_LVM, DEVICE_TYPE_MD)) + nameEntry.set_text(self._device_name_dict[new_type]) + # begin btrfs magic fsCombo = self.builder.get_object("fileSystemTypeCombo") model = fsCombo.get_model()
Now that StorageDevice's format and originalFormat attributes are distinct instances of a DeviceFormat class we have to explicitly duplicate partition removals when we aren't reinitializing the disklabel. All removals are currently done on originalFormat and format still has all of its original partitions, which becomes a problem when we try to add new ones to it. --- pyanaconda/storage/devices.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/pyanaconda/storage/devices.py b/pyanaconda/storage/devices.py index e465c2d..6967b30 100644 --- a/pyanaconda/storage/devices.py +++ b/pyanaconda/storage/devices.py @@ -1540,6 +1540,13 @@ class PartitionDevice(StorageDevice): self.partedPartition = self.disk.originalFormat.partedDisk.getPartitionByPath(self.path) raise
+ if self.disk.format.exists: + # If the new/current disklabel is the same as the original one, we + # have to duplicate the removal on the other copy of the DiskLabel. + part = self.disk.format.partedDisk.getPartitionByPath(self.path) + self.disk.format.removePartition(part) + self.disk.format.commit() + def deactivate(self): """ This is never called. For instructional purposes only.
LUKSDevice instances were getting into the partition list, so instead of setting the partition's max_size we were instead adding that attribute to the LUKSDevice and the following partition allocation run was failing due to incorrect settings on the partitions. --- pyanaconda/storage/__init__.py | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index 3bbdf11..f5004e1 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -1909,12 +1910,12 @@ class Storage(object): container.removeMember(member) members.remove(member) self.formatDevice(member, getFormat("luks")) - member = LUKSDevice("luks-%s" % member.name, + luks_member = LUKSDevice("luks-%s" % member.name, parents=[member], format=getFormat(factory.member_format)) - self.createDevice(member) - members.append(member) - container.addMember(member) + self.createDevice(luks_member) + members.append(luks_member) + container.addMember(luks_member)
member.req_base_size = base_size member.req_size = member.req_base_size @@ -1959,7 +1960,10 @@ class Storage(object): container_size)) size_set = factory.set_class(members, container_size) self.size_sets.append(size_set) - for member in members: + for member in members[:]: + if isinstance(member, LUKSDevice): + member = member.slave + member.req_max_size = size_set.size
try:
--- pyanaconda/ui/gui/spokes/custom.py | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 9241742..d2f3338 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -1780,6 +1780,16 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): self.clear_errors()
with ui_storage_logger(): + factory = self.__storage.getDeviceFactory(device_type, size) + container = self.__storage.getContainer(factory) + + if container: + # don't override user-initiated changes to a defined container + if factory.encrypt_members: + encrypted = container.encrypted + + disks = container.disks + try: self.__storage.newDevice(device_type, size=size, @@ -1797,7 +1807,6 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): except StorageError as e: log.error("newDevice failed: %s" % e) log.debug("trying to find an existing container to use") - factory = self.__storage.getDeviceFactory(device_type, size) container = self.__storage.getContainer(factory, existing=True) log.debug("found container %s" % container) if container:
On Thu, Nov 29, 2012 at 11:19:24AM -0600, David Lehman wrote:
Patch 5 adds support for specifying the names of lvs and mds.
The rest are little improvements, tweaks, and bug fixes.
Ack other than the 2 comments.
anaconda-patches@lists.fedorahosted.org