Example #1
0
    def _setup_slider(self, device, value):
        """Set up the slider for this device, pulling out any previously given
           shrink value as the default.  This also sets up the ticks on the
           slider and keyboard support.  Any devices that are not resizable
           will not have a slider displayed, so they do not need to be worried
           with here.
        """
        self._resizeSlider.handler_block_by_func(self.on_resize_value_changed)
        self._resizeSlider.set_range(device.minSize, device.size)
        self._resizeSlider.handler_unblock_by_func(
            self.on_resize_value_changed)
        self._resizeSlider.set_value(value)

        # The slider needs to be keyboard-accessible.  We'll make small movements change in
        # 1% increments, and large movements in 5% increments.
        distance = device.size - device.minSize
        onePercent = distance * 0.01
        fivePercent = distance * 0.05
        twentyPercent = distance * 0.2

        adjustment = self.builder.get_object("resizeAdjustment")
        adjustment.configure(value, device.minSize, device.size, onePercent,
                             fivePercent, 0)

        # And then the slider needs a couple tick marks for easier navigation.
        self._resizeSlider.clear_marks()
        for i in range(1, 5):
            self._resizeSlider.add_mark(device.minSize + i * twentyPercent,
                                        Gtk.PositionType.BOTTOM, None)

        # Finally, add tick marks for the ends.
        self._resizeSlider.add_mark(device.minSize, Gtk.PositionType.BOTTOM,
                                    size_str(device.minSize))
        self._resizeSlider.add_mark(device.size, Gtk.PositionType.BOTTOM,
                                    size_str(device.size))
    def _setup_slider(self, device, value):
        """Set up the slider for this device, pulling out any previously given
           shrink value as the default.  This also sets up the ticks on the
           slider and keyboard support.  Any devices that are not resizable
           will not have a slider displayed, so they do not need to be worried
           with here.
        """
        self._resizeSlider.set_range(device.minSize, device.size)
        self._resizeSlider.set_value(value)

        # The slider needs to be keyboard-accessible.  We'll make small movements change in
        # 1% increments, and large movements in 5% increments.
        distance = device.size - device.minSize
        onePercent = distance*0.01
        fivePercent = distance*0.05
        twentyPercent = distance*0.2

        adjustment = self.builder.get_object("resizeAdjustment")
        adjustment.configure(value, device.minSize, device.size, onePercent, fivePercent, 0)

        # And then the slider needs a couple tick marks for easier navigation.
        self._resizeSlider.clear_marks()
        for i in range(1, 5):
            self._resizeSlider.add_mark(device.minSize + i*twentyPercent, Gtk.PositionType.BOTTOM, None)

        # Finally, add tick marks for the ends.
        self._resizeSlider.add_mark(device.minSize, Gtk.PositionType.BOTTOM, size_str(device.minSize))
        self._resizeSlider.add_mark(device.size, Gtk.PositionType.BOTTOM, size_str(device.size))
Example #3
0
    def _update_labels(self, nDisks=None, totalReclaimable=None, selectedReclaimable=None):
        if nDisks is not None and totalReclaimable is not None:
            text = P_("<b>%s disk; %s reclaimable space</b> (in filesystems)",
                      "<b>%s disks; %s reclaimable space</b> (in filesystems)",
                      nDisks) % (nDisks, size_str(totalReclaimable))
            self._reclaimable_label.set_markup(text)

        if selectedReclaimable is not None:
            text = _("Total selected space to reclaim: <b>%s</b>") % size_str(selectedReclaimable)
            self._selected_label.set_markup(text)
    def _update_labels(self, nDisks=None, totalReclaimable=None, selectedReclaimable=None):
        if nDisks is not None and totalReclaimable is not None:
            text = P_("<b>%s disk; %s reclaimable space</b> (in filesystems)",
                      "<b>%s disks; %s reclaimable space</b> (in filesystems)",
                      nDisks) % (nDisks, size_str(totalReclaimable))
            self._reclaimable_label.set_markup(text)

        if selectedReclaimable is not None:
            text = _("Total selected space to reclaim: <b>%s</b>") % size_str(selectedReclaimable)
            self._selected_label.set_markup(text)
Example #5
0
    def _update_labels(self, nDisks=None, totalReclaimable=None, selectedReclaimable=None):
        if nDisks is not None and totalReclaimable is not None:
            text = P_("<b>%(count)s disk; %(size)s reclaimable space</b> (in filesystems)",
                      "<b>%(count)s disks; %(size)s reclaimable space</b> (in filesystems)",
                      nDisks) % {"count" : escape_markup(str(nDisks)),
                                 "size" : escape_markup(size_str(totalReclaimable))}
            self._reclaimable_label.set_markup(text)

        if selectedReclaimable is not None:
            text = _("Total selected space to reclaim: <b>%s</b>") % \
                    escape_markup(size_str(selectedReclaimable))
            self._selected_label.set_markup(text)
Example #6
0
    def refresh(self, args=None):
        NormalTUISpoke.refresh(self, args)

        # Join the initialization thread to block on it
        # This print is foul.  Need a better message display
        print(_("Probing storage..."))
        threadMgr.wait(THREAD_STORAGE_WATCHER)

        # synchronize our local data store with the global ksdata
        # Commment out because there is no way to select a disk right
        # now without putting it in ksdata.  Seems wrong?
        #self.selected_disks = self.data.ignoredisk.onlyuse[:]
        self.autopart = self.data.autopart.autopart

        message = self._update_summary()

        # loop through the disks and present them.
        for disk in self.disks:
            size = size_str(disk.size)
            c = CheckboxWidget(
                title="%i) %s: %s (%s)" %
                (self.disks.index(disk) + 1, disk.model, size, disk.name),
                completed=(disk.name in self.selected_disks))
            self._window += [c, ""]

        self._window += [TextWidget(message), ""]

        return True
Example #7
0
    def setup(self, store, selectedNames, disks):
        vendors = []
        interconnects = []

        for disk in disks:
            selected = disk.name in selectedNames

            if hasattr(disk, "node"):
                port = str(disk.node.port)
                lun = str(disk.node.tpgt)
            else:
                port = ""
                lun = ""

            store.append([True, selected, not disk.protected,
                          disk.name, "", disk.model, size_str(disk.size),
                          disk.vendor, disk.bus, disk.serial,
                          self._long_identifier(disk), "", port, getattr(disk, "initiator", ""),
                          lun, ""])

            if not disk.vendor in vendors:
                vendors.append(disk.vendor)

            if not disk.bus in interconnects:
                interconnects.append(disk.bus)

        self._combo.set_active(0)
        self._combo.emit("changed")

        self.setupCombo(self._vendorCombo, vendors)
        self.setupCombo(self._icCombo, interconnects)
Example #8
0
    def setup(self, store, selectedNames, disks):
        vendors = []
        interconnects = []

        for disk in disks:
            paths = [d.name for d in disk.parents]
            selected = disk.name in selectedNames

            store.append([
                True, selected, not disk.protected, disk.name, "", disk.model,
                size_str(disk.size), disk.vendor, disk.bus, disk.serial,
                disk.wwid, "\n".join(paths), "", "", "", "", ""
            ])
            if not disk.vendor in vendors:
                vendors.append(disk.vendor)

            if not disk.bus in interconnects:
                interconnects.append(disk.bus)

        self._combo = self.builder.get_object("multipathTypeCombo")
        self._combo.set_active(0)
        self._combo.emit("changed")

        self.setupCombo(self._vendorCombo, vendors)
        self.setupCombo(self._icCombo, interconnects)
Example #9
0
    def _format_disk_info(self, disk):
        """ Some specialized disks are difficult to identify in the storage
            spoke, so add and return extra identifying information about them.

            Since this is going to be ugly to do within the confines of the
            CheckboxWidget, pre-format the display string right here.
        """
        # show this info for all disks
        format_str = "%s: %s (%s)" % (disk.model, size_str(
            disk.size), disk.name)

        disk_attrs = []
        # now check for/add info about special disks
        if (isinstance(disk, MultipathDevice)
                or isinstance(disk, iScsiDiskDevice)
                or isinstance(disk, FcoeDiskDevice)):
            if hasattr(disk, "wwid"):
                disk_attrs.append(disk.wwid)
        elif isinstance(disk, DASDDevice):
            if hasattr(disk, "busid"):
                disk_attrs.append(disk.busid)
        elif isinstance(disk, ZFCPDiskDevice):
            if hasattr(disk, "fcp_lun"):
                disk_attrs.append(disk.fcp_lun)
            if hasattr(disk, "wwpn"):
                disk_attrs.append(disk.wwpn)
            if hasattr(disk, "hba_id"):
                disk_attrs.append(disk.hba_id)

        # now append all additional attributes to our string
        for attr in disk_attrs:
            format_str += ", %s" % attr

        return format_str
Example #10
0
    def __init__(self, data, storage, payload):
        GUIObject.__init__(self, data)
        self.storage = storage
        self.payload = payload

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

        self._actionStore = self.builder.get_object("actionStore")
        self._diskStore = self.builder.get_object("diskStore")

        self._selection = self.builder.get_object("diskView-selection")

        self._view = self.builder.get_object("diskView")
        self._diskStore = self.builder.get_object("diskStore")
        self._reclaimable_label = self.builder.get_object(
            "reclaimableSpaceLabel")
        self._selected_label = self.builder.get_object("selectedSpaceLabel")

        self._required_label = self.builder.get_object("requiredSpaceLabel")
        markup = self._required_label.get_label()
        self._required_label.set_markup(markup %
                                        size_str(self.payload.spaceRequired))

        self._reclaimDescLabel = self.builder.get_object("reclaimDescLabel")

        self._resizeButton = self.builder.get_object("resizeButton")

        self._preserveButton = self.builder.get_object("preserveButton")
        self._shrinkButton = self.builder.get_object("shrinkButton")
        self._deleteButton = self.builder.get_object("deleteButton")
        self._resizeSlider = self.builder.get_object("resizeSlider")
    def refresh(self, args = None):
        NormalTUISpoke.refresh(self, args)

        # Join the initialization thread to block on it
        # This print is foul.  Need a better message display
        print(_("Probing storage..."))
        threadMgr.wait(THREAD_STORAGE_WATCHER)

        # synchronize our local data store with the global ksdata
        # Commment out because there is no way to select a disk right
        # now without putting it in ksdata.  Seems wrong?
        #self.selected_disks = self.data.ignoredisk.onlyuse[:]
        self.autopart = self.data.autopart.autopart

        message = self._update_summary()

        # loop through the disks and present them.
        for disk in self.disks:
            size = size_str(disk.size)
            c = CheckboxWidget(title="%i) %s: %s (%s)" % (self.disks.index(disk) + 1,
                                                 disk.model, size, disk.name),
                               completed=(disk.name in self.selected_disks))
            self._window += [c, ""]

        self._window += [TextWidget(message), ""]

        return True
Example #12
0
    def setup(self, store, selectedNames, disks):
        """ Set up our Z-page, but only if we're running on s390x. """
        if not self._isS390:
            return
        else:
            ccws = []
            wwpns = []
            luns = []

            self._combo = self.builder.get_object("zTypeCombo")
            self._combo.set_active(0)
            self._combo.emit("changed")

            for disk in disks:
                paths = [d.name for d in disk.parents]
                selected = disk.name in selectedNames

                if getattr(disk, "type") == "zfcp":
                    # remember to store all of the zfcp-related junk so we can
                    # see it in the UI
                    if not disk.fcp_lun in luns:
                        luns.append(disk.fcp_lun)
                    if not disk.wwpn in wwpns:
                        wwpns.append(disk.wwpn)
                    if not disk.hba_id in ccws:
                        ccws.append(disk.hba_id)

                    # now add it to our store
                    store.append([
                        True, selected, not disk.protected, disk.name, "",
                        disk.model,
                        size_str(disk.size), disk.vendor, disk.bus,
                        disk.serial, "", "\n".join(paths), "", "",
                        disk.fcp_lun, disk.hba_id, disk.wwpn
                    ])
    def __init__(self, data, storage, payload):
        GUIObject.__init__(self, data)
        self.storage = storage
        self.payload = payload

        self._actionStore = self.builder.get_object("actionStore")
        self._diskStore = self.builder.get_object("diskStore")

        self._view = self.builder.get_object("diskView")
        self._diskStore = self.builder.get_object("diskStore")
        self._reclaimable_label = self.builder.get_object("reclaimableSpaceLabel")
        self._selected_label = self.builder.get_object("selectedSpaceLabel")

        self._required_label = self.builder.get_object("requiredSpaceLabel")
        markup = self._required_label.get_label()
        self._required_label.set_markup(markup % size_str(self.payload.spaceRequired))

        self._reclaimDescLabel = self.builder.get_object("reclaimDescLabel")

        self._resizeButton = self.builder.get_object("resizeButton")

        self._preserveButton = self.builder.get_object("preserveButton")
        self._shrinkButton = self.builder.get_object("shrinkButton")
        self._deleteButton = self.builder.get_object("deleteButton")
        self._resizeSlider = self.builder.get_object("resizeSlider")
    def setup(self, store, selectedNames, disks):
        vendors = []
        interconnects = []

        for disk in disks:
            paths = [d.name for d in disk.parents]
            selected = disk.name in selectedNames

            store.append([True, selected, not disk.protected,
                          disk.name, "", disk.model, size_str(disk.size),
                          disk.vendor, disk.bus, disk.serial,
                          disk.wwid, "\n".join(paths), "", "",
                          "", ""])
            if not disk.vendor in vendors:
                vendors.append(disk.vendor)

            if not disk.bus in interconnects:
                interconnects.append(disk.bus)

        self._combo = self.builder.get_object("multipathTypeCombo")
        self._combo.set_active(0)
        self._combo.emit("changed")

        self.setupCombo(self._vendorCombo, vendors)
        self.setupCombo(self._icCombo, interconnects)
 def _get_sw_needs_text(self, required_space, auto_swap):
     required_space_text = size_str(required_space)
     sw_text = (_("Your current <a href=\"\"><b>%(product)s</b> software "
                  "selection</a> requires <b>%(total)s</b> of available "
                  "space, including <b>%(software)s</b> for software and "
                  "<b>%(swap)s</b> for swap space.")
                % {"product": productName,
                   "total": required_space + auto_swap,
                   "software": required_space, "swap": auto_swap})
     return sw_text
Example #16
0
    def initialize(self, disks, free, showRemove=True, setBoot=True):
        self._previousID = None

        for disk in disks:
            self._store.append([False,
                                "%s (%s)" % (disk.description, disk.serial),
                                size_str(disk.size),
                                size_str(free[disk.name][0]),
                                disk.name,
                                disk.id])
        self.disks = disks[:]
        self._update_summary()

        if not showRemove:
            self.builder.get_object("remove_button").hide()

        if not setBoot:
            self._set_button.hide()

        if not disks:
            return

        # Don't select a boot device if no boot device is asked for.
        if self.data.bootloader.location == "none":
            return

        # Set up the default boot device.  Use what's in the ksdata if anything,
        # then fall back to the first device.
        default_id = None
        if self.data.bootloader.bootDrive:
            for d in self.disks:
                if d.name == self.data.bootloader.bootDrive:
                    default_id = d.id

        if not default_id:
            default_id = self.disks[0].id

        # And then select it in the UI.
        for row in self._store:
            if row[ID_COL] == default_id:
                self._previousID = row[ID_COL]
                row[IS_BOOT_COL] = True
                break
Example #17
0
 def _get_sw_needs_text(self, required_space, auto_swap):
     required_space_text = size_str(required_space)
     sw_text = (_("Your current <a href=\"\"><b>%(product)s</b> software "
                  "selection</a> requires <b>%(total)s</b> of available "
                  "space, including <b>%(software)s</b> for software and "
                  "<b>%(swap)s</b> for swap space.") % {
                      "product": productName,
                      "total": required_space + auto_swap,
                      "software": required_space,
                      "swap": auto_swap
                  })
     return sw_text
    def _add_disk_overview(self, disk, box):
        if disk.removable:
            kind = "drive-removable-media"
        else:
            kind = "drive-harddisk"

        size = size_str(disk.size)
        if disk.serial:
            popup_info = "%s" % disk.serial
        else:
            popup_info = None

        # We don't want to display the whole huge WWID for a multipath device.
        # That makes the DO way too wide.
        if isinstance(disk, MultipathDevice):
            desc = disk.wwid.split(":")
            description = ":".join(desc[0:3]) + "..." + ":".join(desc[-5:-1])
        else:
            description = disk.description

        free = self.storage.getFreeSpace(disks=[disk])[disk.name][0]

        overview = AnacondaWidgets.DiskOverview(description,
                                                kind,
                                                size,
                                                _("%s free") % size_str(free),
                                                disk.name,
                                                popup=popup_info)
        box.pack_start(overview, False, False, 0)

        # FIXME: this will need to get smarter
        #
        # maybe a little function that resolves each item in onlyuse using
        # udev_resolve_devspec and compares that to the DiskDevice?
        overview.set_chosen(disk.name in self.selected_disks)
        overview.connect("button-press-event", self._on_disk_clicked)
        overview.connect("key-release-event", self._on_disk_clicked)
        overview.connect("focus-in-event", self._on_disk_focus_in)
        overview.show_all()
Example #19
0
    def _add_disk_overview(self, disk, box):
        if disk.removable:
            kind = "drive-removable-media"
        else:
            kind = "drive-harddisk"

        size = size_str(disk.size)
        if disk.serial:
            popup_info = "%s" % disk.serial
        else:
            popup_info = None

        # We don't want to display the whole huge WWID for a multipath device.
        # That makes the DO way too wide.
        if isinstance(disk, MultipathDevice):
            desc = disk.wwid.split(":")
            description = ":".join(desc[0:3]) + "..." + ":".join(desc[-4:])
        else:
            description = disk.description

        free = self.storage.getFreeSpace(disks=[disk])[disk.name][0]

        overview = AnacondaWidgets.DiskOverview(description,
                                                kind,
                                                size,
                                                _("%s free") % size_str(free),
                                                disk.name,
                                                popup=popup_info)
        box.pack_start(overview, False, False, 0)

        # FIXME: this will need to get smarter
        #
        # maybe a little function that resolves each item in onlyuse using
        # udev_resolve_devspec and compares that to the DiskDevice?
        overview.set_chosen(disk.name in self.selected_disks)
        overview.connect("button-press-event", self._on_disk_clicked)
        overview.connect("key-release-event", self._on_disk_clicked)
        overview.connect("focus-in-event", self._on_disk_focus_in)
        overview.show_all()
    def _set_free_space_labels(self, disk_free, fs_free):
        disk_free_text = size_str(disk_free)
        self.disk_free_label.set_text(disk_free_text)

        fs_free_text = size_str(fs_free)
        self.fs_free_label.set_text(fs_free_text)
Example #21
0
 def resize_slider_format(self, scale, value):
     # This makes the value displayed under the slider prettier than just a
     # single number.
     return size_str(value)
 def resize_slider_format(self, scale, value):
     # This makes the value displayed under the slider prettier than just a
     # single number.
     return size_str(value)
Example #23
0
    def populate(self, disks):
        totalDisks = 0
        totalReclaimableSpace = 0

        self._initialFreeSpace = Size(0)
        self._selectedReclaimableSpace = 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 = 0
            else:
                fstype = disk.format.type
                diskReclaimableSpace = disk.size

            itr = self._diskStore.append(None, [
                disk.id,
                "%s %s" % (size_str(disk.size), disk.description), fstype,
                "<span foreground='grey' style='italic'>%s total</span>",
                _(PRESERVE), editable,
                self._get_tooltip(disk), 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": size_str(freeSize), "devSize": size_str(dev.size)}
                        if not dev.protected:
                            canShrinkSomething = True
                    else:
                        freeSize = dev.size
                        resizeString = "<span foreground='grey'>%s</span>" % _(
                            "Not resizeable")

                    self._diskStore.append(itr, [
                        dev.id,
                        self._description(dev), dev.format.type, resizeString,
                        _(PRESERVE), not dev.protected,
                        self._get_tooltip(dev), 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]
            converted = diskFree.convertTo(spec="mb")
            if int(converted):
                self._diskStore.append(itr, [
                    disk.id,
                    _("""<span foreground='grey' style='italic'>Free space</span>"""
                      ), "",
                    "<span foreground='grey' style='italic'>%s</span>" %
                    size_str(diskFree),
                    _(PRESERVE), False,
                    self._get_tooltip(disk),
                    float(converted), ""
                ])
                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] % size_str(diskReclaimableSpace)

            totalDisks += 1
            totalReclaimableSpace += diskReclaimableSpace

        self._update_labels(totalDisks, totalReclaimableSpace, 0)

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

        if canShrinkSomething:
            description += "\n\n"
            description += _(
                "There is also free space available in pre-existing filesystems.  "
                "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)
Example #24
0
    def _set_free_space_labels(self, disk_free, fs_free):
        disk_free_text = size_str(disk_free)
        self.disk_free_label.set_text(disk_free_text)

        fs_free_text = size_str(fs_free)
        self.fs_free_label.set_text(fs_free_text)
    def populate(self, disks):
        totalDisks = 0
        totalReclaimableSpace = 0

        self._initialFreeSpace = Size(0)
        self._selectedReclaimableSpace = 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 = 0
            else:
                fstype = disk.format.type
                diskReclaimableSpace = disk.size

            itr = self._diskStore.append(None, [disk.id,
                                                "%s %s" % (size_str(disk.size), disk.description),
                                                fstype,
                                                "<span foreground='grey' style='italic'>%s total</span>",
                                                _(PRESERVE),
                                                editable,
                                                self._get_tooltip(disk),
                                                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": size_str(freeSize), "devSize": size_str(dev.size)}
                        if not dev.protected:
                            canShrinkSomething = True
                    else:
                        freeSize = dev.size
                        resizeString = "<span foreground='grey'>%s</span>" % _("Not resizeable")

                    self._diskStore.append(itr, [dev.id,
                                                 self._description(dev),
                                                 dev.format.type,
                                                 resizeString,
                                                 _(PRESERVE),
                                                 not dev.protected,
                                                 self._get_tooltip(dev),
                                                 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]
            converted = diskFree.convertTo(spec="mb")
            if int(converted):
                self._diskStore.append(itr, [disk.id,
                                             _("""<span foreground='grey' style='italic'>Free space</span>"""),
                                             "",
                                             "<span foreground='grey' style='italic'>%s</span>" % size_str(diskFree),
                                             _(PRESERVE),
                                             False,
                                             self._get_tooltip(disk),
                                             float(converted),
                                             ""])
                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] % size_str(diskReclaimableSpace)

            totalDisks += 1
            totalReclaimableSpace += diskReclaimableSpace

        self._update_labels(totalDisks, totalReclaimableSpace, 0)

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

        if canShrinkSomething:
            description += "\n\n"
            description += _("There is also free space available in pre-existing filesystems.  "
                             "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)