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")
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)
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
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