예제 #1
0
def on_exit_edit(edit_field, disk_win=None):
    '''On exit, if the user has left the field blank, set the size to 0'''

    text = edit_field.get_text()
    if not text.strip():
        text = "0"
        enctext = text.encode(get_encoding())
        # encode per locale for floating point conversion
        edit_field.set_text("%.1f" % locale.atof(enctext))

    part_order = disk_win.ui_obj.get_parts_in_use().index(edit_field.data_obj)
    LOGGER.debug("Part being resized is at index: %s", part_order)

    new_size_text = text.strip()

    LOGGER.debug("Resizing text=%s", new_size_text)
    # encode user input per locale for floating point conversion
    enctext = new_size_text.encode(get_encoding())
    new_size = Size(str(locale.atof(enctext)) + Size.gb_units)
    old_size = edit_field.data_obj.size

    new_size_byte = new_size.get(Size.byte_units)
    old_size_byte = old_size.get(Size.byte_units)

    precision = Size(UI_PRECISION).get(Size.byte_units)

    if abs(new_size_byte - old_size_byte) > precision:
        parent_doc_obj = edit_field.data_obj.doc_obj.parent
        if isinstance(parent_doc_obj, Disk):
            if isinstance(edit_field.data_obj.doc_obj, Partition):
                resized_obj = parent_doc_obj.resize_partition(
                    edit_field.data_obj.doc_obj, new_size.get(Size.gb_units),
                    size_units=Size.gb_units)
            else:
                resized_obj = parent_doc_obj.resize_slice(
                    edit_field.data_obj.doc_obj, new_size.get(Size.gb_units),
                    size_units=Size.gb_units)
        else:
            resized_obj = parent_doc_obj.resize_slice(
                edit_field.data_obj.doc_obj, new_size.get(Size.gb_units),
                size_units=Size.gb_units)

        if isinstance(resized_obj, Partition):
            resized_obj.in_zpool = ROOT_POOL
        else:
            if resized_obj.in_zpool == ROOT_POOL:
                resized_obj.tag = V_ROOT

        if disk_win is not None:
            disk_win.set_disk_info(ui_obj=disk_win.ui_obj)
            disk_win.activate_index(part_order)

    dump_doc("After resize")
예제 #2
0
    def create(self, dry_run):
        """ method to create a zvol.
        """
        if not self.exists:
            # check self.size.  If it's a Size() object, convert it to a string
            # ZFS expects
            if isinstance(self.size, Size):
                zvol_size = str(int(self.size.get(Size.mb_units))) + "M"
            elif self.size == "max":
                # Allocate 90 % of available space on pool to zvol.
                # Size of zvol is capped to 90 % to avoid full zpool
                # issues.
                if self.parent is not None:
                    fs = Filesystem(self.parent.name)
                    fs_size = Size(fs.get("available"))
                    zvol_size = str(int(fs_size.get(Size.mb_units) * 0.9)) + \
                                    "M"
                    self.size = Size(zvol_size)
            else:
                zvol_size = self.size

            cmd = [ZFS, "create", "-p", "-V", zvol_size]

            zfs_options = self.get_first_child(class_type=Options)
            if zfs_options is not None:
                cmd.extend(zfs_options.get_arg_list())

            cmd.append(self.full_name)

            if not dry_run:
                Popen.check_call(cmd, stdout=Popen.STORE, stderr=Popen.STORE,
                                 logger=ILN, env={"LC_ALL": "C"})

                # check the "use" attribute
                if self.use == "swap":
                    cmd = [SWAP, "-a",
                           os.path.join("/dev/zvol/dsk", self.full_name)]
                    Popen.check_call(cmd, stdout=Popen.STORE,
                                     stderr=Popen.STORE, logger=ILN,
                                     stderr_loglevel=logging.DEBUG)
                elif self.use == "dump":
                    cmd = [DUMPADM, "-d",
                           os.path.join("/dev/zvol/dsk", self.full_name)]
                    if self.create_failure_ok:
                        results = (0, 1)
                    else:
                        results = (0,)
                    p = Popen.check_call(cmd, stdout=Popen.STORE,
                                         stderr=Popen.STORE, logger=ILN,
                                         stderr_loglevel=logging.DEBUG,
                                         check_result=results)
                    if p.returncode == 1:
                        logger = logging.getLogger(ILN)
                        logger.warning("Unable to create dump Zvol "
                                       "with size %s." % zvol_size)
예제 #3
0
def decimal_valid(edit_field, disk_win=None):
    '''Check text to see if it is a decimal number of precision no
    greater than the tenths place.

    '''
    text = edit_field.get_text().lstrip()
    radixchar = locale.localeconv()['decimal_point']
    if text.endswith(" "):
        raise UIMessage(_('Only the digits 0-9 and %s are valid.') % radixchar)
    vals = text.split(radixchar)
    if len(vals) > 2:
        raise UIMessage(_('A number can only have one %s') % radixchar)
    try:
        if len(vals[0]) > 0:
            int(vals[0])
        if len(vals) > 1 and len(vals[1]) > 0:
            int(vals[1])
    except ValueError:
        raise UIMessage(_('Only the digits 0-9 and %s are valid.') % radixchar)
    if len(vals) > 1 and len(vals[1]) > 1:
        raise UIMessage(_("Size can be specified to only one decimal place."))
    if disk_win is not None:
        text = text.rstrip(radixchar)
        if not text:
            text = "0"

        # encode user input per locale for floating point conversion
        text = text.encode(get_encoding())
        new_size = Size(str(locale.atof(text)) + Size.gb_units)
        max_size = edit_field.data_obj.get_max_size()

        # When comparing sizes, check only to the first decimal place,
        # as that is all the user sees. (Rounding errors that could
        # cause the partition/slice layout to be invalid get cleaned up
        # prior to target instantiation)
        new_size_rounded = round(new_size.get(Size.gb_units), 1)
        max_size_rounded = round(max_size.get(Size.gb_units), 1)
        if new_size_rounded > max_size_rounded:
            locale_new_size = locale.format("%.1f", new_size_rounded)
            locale_max_size = locale.format("%.1f", max_size_rounded)
            msg = _("The new size ") + locale_new_size + \
                _(" is greater than the available space ") + locale_max_size
            raise UIMessage(msg)
    return True
예제 #4
0
def resize_validate(edit_field, disk_win=None):
    '''Check text to see if it is a decimal number of precision no greater
       than the tenths place. Resize the partition if everything checks
       out.
    '''

    LOGGER.debug("in resize_validate()")
    text = edit_field.get_text().lstrip()
    radixchar = locale.localeconv()['decimal_point']
    if text.endswith(" "):
        raise UIMessage(
            _('Only the digits 0-9 and "%s" are valid.') % radixchar)
    vals = text.split(radixchar)
    if len(vals) > 2:
        raise UIMessage(_('A number can only have one "%s"') % radixchar)
    try:
        if len(vals[0]) > 0:
            int(vals[0])
        if len(vals) > 1 and len(vals[1]) > 0:
            int(vals[1])
    except ValueError:
        raise UIMessage(
            _('Only the digits 0-9 and "%s" are valid.') % radixchar)
    if len(vals) > 1 and len(vals[1]) > 1:
        raise UIMessage(_("Size can be specified to only one decimal place."))

    if disk_win is None:
        return True

    text = text.rstrip(radixchar)
    # If the user deleted all digits, leave partition size alone until user
    # inputs new digits
    if not text:
        LOGGER.debug("No size value digits, skipping resize")
        return True

    part_order = disk_win.ui_obj.get_parts_in_use().index(edit_field.data_obj)
    LOGGER.debug("Part being resized is at index: %s", part_order)

    # encode user input per locale for floating point conversion
    text = text.encode(get_encoding())
    new_size = Size(str(locale.atof(text)) + Size.gb_units)
    max_size = edit_field.data_obj.get_max_size()

    # When comparing user input and display sizes, check only to the first
    # decimal place as that is all the user sees.
    new_size_rounded = round(new_size.get(Size.gb_units), 1)
    max_size_rounded = round(max_size.get(Size.gb_units), 1)
    if new_size_rounded > max_size_rounded:
        locale_new_size = locale.format("%.1f", new_size_rounded)
        locale_max_size = locale.format("%.1f", max_size_rounded)
        msg = _("The new size %(size)s is greater than "
                "the available space %(avail)s") % \
                {"size": locale_new_size,
                 "avail": locale_max_size}
        raise UIMessage(msg)

    new_size_text = text.strip()
    LOGGER.debug("New size text=%s", new_size_text)

    old_size = edit_field.data_obj.size
    new_size_byte = new_size.get(Size.byte_units)

    # Filter out edits that would result in resizing a partition to zero
    if new_size_byte == 0:
        return True

    old_size_byte = old_size.get(Size.byte_units)
    precision_bytes = Size(UI_PRECISION).get(Size.byte_units)

    # Ignore potential rounding artifacts.
    if abs(new_size_byte - old_size_byte) <= precision_bytes:
        return True

    max_size_byte = max_size.get(Size.byte_units)

    if new_size_byte > max_size_byte:
        # Allow for loss of precision from rounding errors, but no greater
        if (new_size_byte - max_size_byte) > precision_bytes:
            raise RuntimeError("Requested partition resize to %d bytes "
                               "exceeds maximum size available: %d" %
                               (new_size_byte, max_size_byte))

        # Clamp the new size at max size otherwise the resize will throw
        # an InsufficientSpaceError.
        LOGGER.debug(
            "Requested partition resize exceeds maximum size: "
            "Clamping %d bytes to %d bytes", new_size_byte, max_size_byte)
        new_size = max_size
    parent_doc_obj = edit_field.data_obj.doc_obj.parent
    if isinstance(parent_doc_obj, Disk):
        if isinstance(edit_field.data_obj.doc_obj, GPTPartition):
            resized_obj = parent_doc_obj.resize_gptpartition(
                edit_field.data_obj.doc_obj,
                new_size.get(Size.gb_units),
                size_units=Size.gb_units)
        elif isinstance(edit_field.data_obj.doc_obj, Partition):
            resized_obj = parent_doc_obj.resize_partition(
                edit_field.data_obj.doc_obj,
                new_size.get(Size.gb_units),
                size_units=Size.gb_units)
        else:
            resized_obj = parent_doc_obj.resize_slice(
                edit_field.data_obj.doc_obj,
                new_size.get(Size.gb_units),
                size_units=Size.gb_units)
    else:
        resized_obj = parent_doc_obj.resize_slice(edit_field.data_obj.doc_obj,
                                                  new_size.get(Size.gb_units),
                                                  size_units=Size.gb_units)

    if isinstance(resized_obj, Partition):
        # Don't do this for GPTPartition because there is no guarantee this
        # will be the installation target partition if there is more than
        # 1 Solaris partition
        resized_obj.in_zpool = ROOT_POOL
    elif isinstance(resized_obj, Slice):
        if resized_obj.in_zpool == ROOT_POOL:
            resized_obj.tag = V_ROOT

    disk_win.set_disk_info(ui_obj=disk_win.ui_obj)
    disk_win.activate_index(part_order)

    dump_doc("After resize")

    return True