def updateMenus(self): self.createPartition.setVisible(True) activatePartition = False freePartition = hasFreeDiskSpace(self.storage) if freePartition: activatePartition = True activateVolumeGroup = False availablePVS = len(self.storage.unusedPVS()) if (lvm.has_lvm() and formats.getFormat("lvmpv").supported and availablePVS > 0): activateVolumeGroup = True activateRaidArray = False availableRaidMembers = len(self.storage.unusedRaidMembers()) availableMinors = len(self.storage.unusedRaidMinors) if (availableMinors > 0 and formats.getFormat("software RAID").supported and availableRaidMembers > 1): activateRaidArray = True """if (not activatePartition and not activateVolumeGroup): self.intf.messageWindow(_("Cannot perform any creation operation"), _("Note that the creation operation requires one of the\nfollowing:" " * Free space in one of the Hard Drives.\n" " * At least one free physical volume (LVM) partition.\n" " * At least one Volume Group with free space."), customIcon="warning") return""" freeVolumeGroupSpace = [] for vg in self.storage.vgs: if vg.freeSpace > 0: freeVolumeGroupSpace.append(vg) activateLogicalVolume = False if len(freeVolumeGroupSpace) > 0: activateLogicalVolume = True if activatePartition: self.createPartition.setVisible(True) self.createPhysicalVolume.setVisible(True) self.createRaidMember.setVisible(True) if activateVolumeGroup: self.createVolumeGroup.setVisible(True) self.createLogicalVolume.setVisible(True) if activateLogicalVolume: #FIXME: find way to show only logical volume editor pass if activateRaidArray: self.createRaidArray.setVisible(True)
def newLogicalVolume(self, *args, **kwargs): """ Return a new LogicalVolumeDevice instance. """ if kwargs.has_key("vg"): vg = kwargs.pop("vg") mountpoint = kwargs.pop("mountpoint", None) if kwargs.has_key("fmt_type"): kwargs["format"] = getFormat(kwargs.pop("fmt_type"), mountpoint=mountpoint) if kwargs.has_key("name"): name = kwargs.pop("name") else: if kwargs.get("format") and kwargs["format"].type == "swap": swap = True else: swap = False name = self.createSuggestedLogicalVolumeName(vg, swap=swap, mountpoint=mountpoint) if name in [d.name for d in self.devices]: raise ValueError("name already in use") return LogicalVolume(name, vg, *args, **kwargs)
def formatTypeChanged(self, index): format = formats.getFormat(str(self.sender().itemText(index))) if format.mountable: self.mountpointMenu.setEnabled(True) else: self.mountpointMenu.setEnabled(False) self.mountpointMenu.setCurrentIndex(0)
def add(self): if self.availableLogicalVolumes < 1: self.parent.intf.messageWindow(_("No free slots"), _("You cannot create more than %d logical volume \n" "per volume group.") % (lvm.MAX_LV_SLOTS,), type="warning") return (total, used, free) = self.computeSpace() if free <= 0: self.parent.intf.messageWindow(_("No free space"), _("There is no room left in the volume group to create new\n" "logical volumes. To add a logical volume you must reduce\n" "the size of one or more of the currently existing logical\n" "volumes"), type="warning") return tempvg = self.tmpVolumeGroup name = self.parent.storage.createSuggestedLogicalVolumeName(tempvg) format = formats.getFormat(self.parent.storage.defaultFSType) self.parent.lvs[name] = {'name': name, 'size': free, 'format': format, 'originalFormat': format, 'stripes': 1, 'logSize': 0, 'snapshotSpace': 0, 'exists': False} tempvg = self.tmpVolumeGroup device = self.getLogicalVolumeByName(name, vg=tempvg) self.editLogicalVolume(device, isNew=True)
def mountPointChanged(self, index): print("mount point", self.mountpointMenu.itemText(index)) print(formats.getFormat("efi").type) if yali.util.isEfi() and self.mountpointMenu.itemText( index) == "/boot/efi": self.filesystemMenu.setCurrentIndex( self.filesystemMenu.findText(formats.getFormat("efi").type)) elif self.mountpointMenu.itemText(index) == "/boot": self.filesystemMenu.setCurrentIndex( self.filesystemMenu.findText( formats.get_default_filesystem_type(boot=True))) if self.formatRadio.isVisible(): self.radioButton.setChecked(True) print("partition_gui.py line 329 type must be bool ->", type(self.mountpointMenu.itemData(index))) self.formatRadio.setChecked(self.mountpointMenu.itemData(index))
def _setFormat(self, format): """ Set the Device's format. """ if not format: format = getFormat(None, device=self.path, exists=self.exists) ctx.logger.debug("Setting abstract format to %s" % self.path) if self._format and self._format.status: raise DeviceError("cannot replace active format", self.name) self._format = format
def mountPointChanged(self, index): if yali.util.isEfi() and self.mountpointMenu.itemText(index) == "/boot/efi": self.filesystemMenu.setCurrentIndex(self.filesystemMenu.findText(formats.getFormat("efi").name)) elif self.mountpointMenu.itemText(index) == "/boot": self.filesystemMenu.setCurrentIndex(self.filesystemMenu.findText(formats.get_default_filesystem_type(boot=True))) if self.formatRadio.isVisible(): self.radioButton.setChecked(True) self.formatRadio.setChecked(self.mountpointMenu.itemData(index).toBool())
def editLogicalVolume(self, lv=None, vg=None): """Will be consistent with the state of things and use this funciton for creating and editing LVs. lv -- the logical volume to edit. If this is set there is no need for the other two arguments. vg -- the volume group where the new lv is going to be created. This will only be relevant when we are createing an LV. """ if lv != None: volumegroupEditor = LVMEditor(self, lv.vg, isNew=False) lv = volumegroupEditor.lvs[lv.lvname] isNew = False elif vg != None: volumegroupEditor = LVMEditor(self, vg, isNew=False) tempvg = volumegroupEditor.tmpVolumeGroup name = self.storage.createSuggestedLogicalVolumeName(tempvg) format = formats.getFormat(self.storage.defaultFSType) volumegroupEditor.lvs[name] = { 'name': name, 'size': vg.freeSpace, 'format': format, 'originalFormat': format, 'stripes': 1, 'logSize': 0, 'snapshotSpace': 0, 'exists': False } lv = volumegroupEditor.lvs[name] isNew = True else: return while True: #volumegroupEditor.editLogicalVolume(lv, isNew=isNew) operations = volumegroupEditor.run() for operation in operations: self.storage.devicetree.addOperation(operation) if self.refresh(justRedraw=True): operations.reverse() for operation in operations: self.storage.devicetree.removeOperation(operation) if self.refresh(): raise RuntimeError, ("Returning partitions to state " "prior to edit failed") continue else: break volumegroupEditor.destroy()
def mountPointChanged(self, index): print "mount point", self.mountpointMenu.itemText(index) if yali.util.isEfi() and self.mountpointMenu.itemText(index) == "/boot/efi": self.filesystemMenu.setCurrentIndex(self.filesystemMenu.findText(formats.getFormat("efi").name)) elif self.mountpointMenu.itemText(index) == "/boot": self.filesystemMenu.setCurrentIndex(self.filesystemMenu.findText(formats.get_default_filesystem_type(boot=True))) if self.formatRadio.isVisible(): self.radioButton.setChecked(True) print "partition_gui.py line 329 type must be bool ->", type(self.mountpointMenu.itemData(index)) self.formatRadio.setChecked(self.mountpointMenu.itemData(index))
def editLogicalVolume(self, lv=None, vg=None): """Will be consistent with the state of things and use this funciton for creating and editing LVs. lv -- the logical volume to edit. If this is set there is no need for the other two arguments. vg -- the volume group where the new lv is going to be created. This will only be relevant when we are createing an LV. """ if lv != None: volumegroupEditor = LVMEditor(self, lv.vg, isNew=False) lv = volumegroupEditor.lvs[lv.lvname] isNew = False elif vg != None: volumegroupEditor = LVMEditor(self, vg, isNew=False) tempvg = volumegroupEditor.tmpVolumeGroup name = self.storage.createSuggestedLogicalVolumeName(tempvg) format = formats.getFormat(self.storage.defaultFSType) volumegroupEditor.lvs[name] = {'name': name, 'size': vg.freeSpace, 'format': format, 'originalFormat': format, 'stripes': 1, 'logSize': 0, 'snapshotSpace': 0, 'exists': False} lv = volumegroupEditor.lvs[name] isNew = True else: return while True: #volumegroupEditor.editLogicalVolume(lv, isNew=isNew) operations = volumegroupEditor.run() for operation in operations: self.storage.devicetree.addOperation(operation) if self.refresh(justRedraw=True): operations.reverse() for operation in operations: self.storage.devicetree.removeOperation(operation) if self.refresh(): raise RuntimeError, ("Returning partitions to state " "prior to edit failed") continue else: break volumegroupEditor.destroy()
def mountPointChanged(self, index): if yali.util.isEfi() and self.mountpointMenu.itemText( index) == "/boot/efi": self.filesystemMenu.setCurrentIndex( self.filesystemMenu.findText(formats.getFormat("efi").name)) elif self.mountpointMenu.itemText(index) == "/boot": self.filesystemMenu.setCurrentIndex( self.filesystemMenu.findText( formats.get_default_filesystem_type(boot=True))) if self.formatRadio.isVisible(): self.radioButton.setChecked(True) self.formatRadio.setChecked( self.mountpointMenu.itemData(index).toBool())
def newRaidArray(self, *args, **kwargs): """ Return a new MDRaidArrayDevice instance for configuring. """ if kwargs.has_key("fmt_type"): kwargs["format"] = getFormat(kwargs.pop("fmt_type"), mountpoint=kwargs.pop("mountpoint",None)) if kwargs.has_key("minor"): kwargs["minor"] = int(kwargs["minor"]) else: kwargs["minor"] = self.unusedRaidMinors[0] if kwargs.has_key("name"): name = kwargs.pop("name") else: name = "md%d" % kwargs["minor"] return RaidArray(name, *args, **kwargs)
def newRaidArray(self, *args, **kwargs): """ Return a new MDRaidArrayDevice instance for configuring. """ if kwargs.has_key("fmt_type"): kwargs["format"] = getFormat(kwargs.pop("fmt_type"), mountpoint=kwargs.pop( "mountpoint", None)) if kwargs.has_key("minor"): kwargs["minor"] = int(kwargs["minor"]) else: kwargs["minor"] = self.unusedRaidMinors[0] if kwargs.has_key("name"): name = kwargs.pop("name") else: name = "md%d" % kwargs["minor"] return RaidArray(name, *args, **kwargs)
def newPartition(self, *args, **kwargs): """ Return a new PartitionDevice instance for configuring. """ if kwargs.has_key("fmt_type"): kwargs["format"] = getFormat(kwargs.pop("fmt_type"), mountpoint=kwargs.pop("mountpoint",None), **kwargs.pop("fmt_args", {})) if kwargs.has_key("disks"): parents = kwargs.pop("disks") if isinstance(parents, Device): kwargs["parents"] = [parents] else: kwargs["parents"] = parents if kwargs.has_key("name"): name = kwargs.pop("name") else: name = "req%d" % self.nextID return Partition(name, *args, **kwargs)
def newPartition(self, *args, **kwargs): """ Return a new PartitionDevice instance for configuring. """ if kwargs.has_key("fmt_type"): kwargs["format"] = getFormat(kwargs.pop("fmt_type"), mountpoint=kwargs.pop( "mountpoint", None), **kwargs.pop("fmt_args", {})) if kwargs.has_key("disks"): parents = kwargs.pop("disks") if isinstance(parents, Device): kwargs["parents"] = [parents] else: kwargs["parents"] = parents if kwargs.has_key("name"): name = kwargs.pop("name") else: name = "req%d" % self.nextID return Partition(name, *args, **kwargs)
def formatTypeChanged(self, index): # setMaximum if maxSize ?< self.origrequest.req_size format = formats.getFormat(str(self.sender().itemText(index))) self.enableMountpoint(format) if format.type == "efi": self.mountpointMenu.setCurrentText("/boot/efi") if not self.origrequest.exists: if self.parent.isNew: maxsize = self.parent.partedPartition.getSize(unit="MB") if 0 < format.maxSize < maxsize: maxsize = format.maxSize self.sizeSpin.setMaximum(maxsize) self.sizeSlider.setMaximum(maxsize) elif not self.parent.isNew and self.origrequest.req_size: maxsize = self.origrequest.req_size if 0 < format.maxSize < maxsize: maxsize = format.maxSize self.sizeSpin.setMaximum(maxsize) self.sizeSpin.setValue(maxsize) self.sizeSlider.setMaximum(maxsize) self.sizeSlider.setValue(maxsize)
def formatTypeChanged(self, index): format = formats.getFormat(str(self.sender().itemText(index))) self.enableMountpoint(format)
def formatRadioToggled(self, checked): if checked: format = formats.getFormat(str(self.formatCombo.currentText())) self.enableMountpoint(format)
def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] raidmembers = [] if not rc: self.destroy() return [] widget = self.dialog.content mountpoint = unicode(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, type="error") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint, ), type="warning") continue for index in range(widget.raidMembers.count()): if widget.raidMembers.item(index).checkState() == Qt.Checked: raidmembers.append( widget.raidMembers.item(index).partition) # The user has to select some devices to be part of the array. if not raidmembers: raidlevel = int( widget.raidLevels.itemData( widget.raidLevels.currentIndex())) self.intf.messageWindow( _("Invalid Raid Members"), _("A RAID%(level)d set requires at least %(min_member)d member" ) % { "level": raidlevel, "min_member": raid.get_raid_min_members(raidlevel) }, type="warning") continue if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) raidminor = int( widget.raidMinors.itemData( widget.raidMinors.currentIndex())) raidlevel = int( widget.raidLevels.itemData( widget.raidLevels.currentIndex())) if not raid.isRaid(raid.RAID0, raidlevel): spares = widget.spareSpin.value() else: spares = 0 format = formats.getFormat(formatType, mountpoint=mountpoint) members = len(raidmembers) - spares try: request = self.storage.newRaidArray( minor=raidminor, level=raidlevel, format=format, parents=raidmembers, totalDevices=len(raidmembers), memberDevices=members) except ValueError, msg: self.intf.messageWindow(_("Invalid Raid Members"), unicode(msg), type="warning") continue if not self.isNew: # This may be handled in devicetree.registerAction, # but not in case when we change minor and thus # device name/path (at least with current md) operations.append(OperationDestroyDevice(self.origrequest)) operations.append(OperationCreateDevice(request)) operations.append(OperationCreateFormat(request)) else: format = None if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) operations.append( OperationCreateFormat(self.origrequest, format)) else: cancel = [] cancel.extend( self.storage.devicetree.findOperations( type="destroy", object="format", devid=self.origrequest.id)) cancel.extend( self.storage.devicetree.findOperations( type="create", object="format", devid=self.origrequest.id)) for operation in cancel: self.storage.devicetree.removeOperation(operation) self.origrequest.format = self.origrequest.originalFormat if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(self.origrequest)) if self.origrequest.format.exists and not format and \ self.storage.formatByDefault(self.origrequest): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break
def updateMenus(self): self.createPartition.setVisible(True) activatePartition = False try: freePartition = hasFreeDiskSpace(self.storage) except AttributeError, msg: ctx.logger.debug(msg) else: if freePartition: activatePartition = True activateVolumeGroup = False availablePVS = len(self.storage.unusedPVS()) if (lvm.has_lvm() and formats.getFormat("lvmpv").supported and availablePVS > 0): activateVolumeGroup = True activateRaidArray = False availableRaidMembers = len(self.storage.unusedRaidMembers()) availableMinors = len(self.storage.unusedRaidMinors) if (availableMinors > 0 and formats.getFormat("mdmember").supported and availableRaidMembers > 1): activateRaidArray = True """if (not activatePartition and not activateVolumeGroup): self.intf.messageWindow(_("Cannot perform any creation operation"), _("Note that the creation operation requires one of the\nfollowing:"
def run(self): if self.dialog is None: return None while 1: rc = self.dialog.exec_() if not rc: if self.isNew: if self.parent.parent.lvs.has_key(self.origrequest.lvname): del self.parent.parent.lvs[self.origrequest.lvname] self.destroy() return None format = None widget = self.dialog.content format = self.origrequest.format mountpoint = unicode(widget.mountpointMenu.currentText()) if mountpoint and widget.mountpointMenu.isEditable(): msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, type="error") continue if not self.origrequest.exists: format_type = str(widget.filesystemMenu.currentText()) else: format_type = str(widget.formatCombo.currentText()) format_class = formats.getFormat(format_type) if mountpoint and format_class.mountable: used = False current_mountpoint = getattr(format, "mountpoint", None) for lv in self.parent.parent.lvs.values(): format = lv["format"] if not format.mountable or current_mountpoint and \ format.mountpoint == current_mountpoint: continue if format.mountpoint == mountpoint: used = True break for (mp, dev) in self.parent.parent.storage.mountpoints.iteritems(): if (dev.type != "lvmlv" or dev.vg.id != self.origrequest.vg.id) and mp == mountpoint: used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), type="warning") continue name = str(widget.name.text()) if not self.origrequest.exists: msg = sanityCheckLogicalVolumeName(name) if msg: self.intf.messageWindow(_("Illegal Logical Volume Name"), msg, type="warning") continue # check that the name is not already in use used = 0 for lv in self.parent.parent.lvs.values(): if self.origrequest.lvname != name and lv['name'] == name: used = 1 break if used: self.intf.messageWindow(_("Illegal logical volume name"), _("The logical volume name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue if not self.origrequest.exists: badsize = 0 try: size = long(widget.sizeSpin.value()) except: size = 1 if badsize or size <= 0: self.intf.messageWindow(_("Illegal size"), _("The requested size as entered is " "not a valid number greater than 0."), type="warning") continue else: size = self.origrequest.size # check that size specification is within limits peSize = int(self.parent.physicalExtends.itemData(self.parent.physicalExtends.currentIndex())) / 1024 size = lvm.clampSize(size, peSize, roundup=True) maximumVolumeSize = lvm.getMaxLVSize() if size > maximumVolumeSize: self.intf.messageWindow(_("Not enough space"), _("The current requested size " "(%(size)10.2f MB) is larger than " "the maximum logical volume size " "(%(maxlv)10.2f MB). " "To increase this limit you can " "create more Physical Volumes from " "unpartitioned disk space and " "add them to this Volume Group.") % {'size': size, 'maxlv': maximumVolumeSize}, type="warning") continue # Get format origname = self.origrequest.lvname if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) self.origrequest._name = name try: self.origrequest.size = size except ValueError, msg: self.intf.messageWindow(_("Not enough space"), _("The size entered for this " "logical volume (%(size)d MB) " "combined with the size of the " "other logical volume(s) " "exceeds the size of the " "volume group (%(tmpvgsize)d " "MB). Please make the volume " "group larger or make the " "logical volume smaller.") % {'size': size, 'tmpvgsize': self.origrequest.vg.size}, type="warning") continue else: self.origrequest.format = format else: if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) self.origrequest.format = format else: self.origrequest.format = self.origrequest.originalFormat if widget.migrateRadio.isChecked(): self.origrequest.format.migrate = True if widget.resizeRadio.isChecked(): self.origrequest.targetSize = widget.resizeSpin.value() if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if self.origrequest.format.exists and \ self.origrequest.format.mountable and \ self.origrequest.format.mountpoint: if self.storage.formatByDefault(self.origrequest) and \ not queryNoFormatPreExisting(self.intf): continue # everything ok break
def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: if self.isNew: if self.lvs.has_key(self.origrequest.name): del self.lvs[self.origrequest.name] self.destroy() return [] widget = self.dialog.content name = str(widget.name.text()) pvs = widget.selectedPhysicalVolumes msg = sanityCheckVolumeGroupName(name) if msg: self.intf.messageWindow(_("Invalid Volume Group Name"), msg, type="warning") continue origname = self.origrequest.name if origname != name: if name in [vg.name for vg in self.storage.vgs]: self.intf.messageWindow(_("Name in use"), _("The volume group name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue peSize = widget.physicalExtends.itemData(widget.physicalExtends.currentIndex()).toInt()[0] / 1024.0 origlvs = self.origrequest.lvs if not self.origrequest.exists: ctx.logger.debug("non-existing vg -- setting up lvs, pvs, name, peSize") for lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) for pv in self.origrequest.pvs: if pv not in self.pvs: self.origrequest._removePhysicalVolume(pv) for pv in self.pvs: if pv not in self.origrequest.pvs: self.origrequest._addPhysicalVolume(pv) self.origrequest.name = name self.origrequest.peSize = peSize if self.isNew: operations = [OperationCreateDevice(self.origrequest)] for lv in origlvs: ctx.logger.debug("old lv %s..." % lv.lvname) if not lv.exists or lv.lvname not in self.lvs or \ (not self.lvs[lv.lvname]['exists'] and lv.exists): ctx.logger.debug("removing lv %s" % lv.lvname) if lv.format.type: operations.append(OperationDestroyFormat(lv)) if lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) operations.append(OperationDestroyDevice(lv)) # schedule creation of all new lvs, their formats, luks devices, &c tempvg = widget.tmpVolumeGroup for lv in tempvg.lvs: ctx.logger.debug("new lv %s" % lv) if not lv.exists: ctx.logger.debug("creating lv %s" % lv.lvname) logicalvolume = LogicalVolume(lv.lvname, self.origrequest, size=lv.size) operations.append(OperationCreateDevice(logicalvolume)) # create the format mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=logicalvolume.path) operations.append(OperationCreateFormat(logicalvolume, format)) else: ctx.logger.debug("lv %s already exists" % lv.lvname) origlv = widget.getLogicalVolumeByName(lv.lvname) if lv.resizable and lv.targetSize != origlv.size: operations.append(OperationResizeDevice(origlv, lv.targetSize)) if lv.format.exists: ctx.logger.debug("format already exists") usedev = origlv format = lv.format if format == usedev.originalFormat: cancel = [] cancel.extend(self.parent.storage.devicetree.findOperations(type="create", object="format", devid=origlv.id)) cancel.extend(self.parent.storage.devicetree.findOperations(type="destroy", object="format", devid=origlv.id)) for operation in cancel: self.storage.devicetree.cancelOperation(operation) if hasattr(format, "mountpoint"): usedev.format.mountpoint = format.mountpoint if format.migratable and format.migrate and \ not usedev.format.migrate: usedev.format.migrate = format.migrate operations.append(OperationMigrateFormat(usedev)) if format.resizable and lv.format.resizable and \ lv.targetSize != format.targetSize and \ lv.targetSize != lv.currentSize and \ usedev.format.exists: ctx.logger.debug("resizing format on %s to %d" % (usedev.lvname, lv.targetSize)) operations.append(OperationResizeFormat(usedev, lv.targetSize)) elif lv.format.type: ctx.logger.debug("new format: %s" % lv.format.type) if origlv.format.type: operations.append(OperationDestroyFormat(origlv)) mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=origlv.path) operations.append(OperationCreateFormat(origlv, format)) else: ctx.logger.debug("no format!") break return operations
def run(self): if self.dialog is None: return None while 1: rc = self.dialog.exec_() if not rc: if self.isNew: if self.parent.parent.lvs.has_key(self.origrequest.lvname): del self.parent.parent.lvs[self.origrequest.lvname] self.destroy() return None format = None widget = self.dialog.content format = self.origrequest.format mountpoint = unicode(widget.mountpointMenu.currentText()) if mountpoint and widget.mountpointMenu.isEditable(): msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, type="error") continue if not self.origrequest.exists: format_type = str(widget.filesystemMenu.currentText()) else: format_type = str(widget.formatCombo.currentText()) format_class = formats.getFormat(format_type) if mountpoint and format_class.mountable: used = False current_mountpoint = getattr(format, "mountpoint", None) for lv in self.parent.parent.lvs.values(): format = lv["format"] if not format.mountable or current_mountpoint and \ format.mountpoint == current_mountpoint: continue if format.mountpoint == mountpoint: used = True break for (mp, dev) in self.parent.parent.storage.mountpoints.iteritems(): if (dev.type != "lvmlv" or dev.vg.id != self.origrequest.vg.id) and mp == mountpoint: used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), type="warning") continue name = str(widget.name.text()) if not self.origrequest.exists: msg = sanityCheckLogicalVolumeName(name) if msg: self.intf.messageWindow(_("Illegal Logical Volume Name"), msg, type="warning") continue # check that the name is not already in use used = 0 for lv in self.parent.parent.lvs.values(): if self.origrequest.lvname != name and lv['name'] == name: used = 1 break if used: self.intf.messageWindow(_("Illegal logical volume name"), _("The logical volume name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue if not self.origrequest.exists: badsize = 0 try: size = long(widget.sizeSpin.value()) except: size = 1 if badsize or size <= 0: self.intf.messageWindow(_("Illegal size"), _("The requested size as entered is " "not a valid number greater than 0."), type="warning") continue else: size = self.origrequest.size # check that size specification is within limits peSize = self.parent.physicalExtends.itemData(self.parent.physicalExtends.currentIndex()).toInt()[0] / 1024 size = lvm.clampSize(size, peSize, roundup=True) maximumVolumeSize = lvm.getMaxLVSize() if size > maximumVolumeSize: self.intf.messageWindow(_("Not enough space"), _("The current requested size " "(%(size)10.2f MB) is larger than " "the maximum logical volume size " "(%(maxlv)10.2f MB). " "To increase this limit you can " "create more Physical Volumes from " "unpartitioned disk space and " "add them to this Volume Group.") % {'size': size, 'maxlv': maximumVolumeSize}, type="warning") continue # Get format origname = self.origrequest.lvname if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) self.origrequest._name = name try: self.origrequest.size = size except ValueError, msg: self.intf.messageWindow(_("Not enough space"), _("The size entered for this " "logical volume (%(size)d MB) " "combined with the size of the " "other logical volume(s) " "exceeds the size of the " "volume group (%(tmpvgsize)d " "MB). Please make the volume " "group larger or make the " "logical volume smaller.") % {'size': size, 'tmpvgsize': self.origrequest.vg.size}, type="warning") continue else: self.origrequest.format = format else: if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) self.origrequest.format = format else: self.origrequest.format = self.origrequest.originalFormat if widget.migrateRadio.isChecked(): self.origrequest.format.migrate = True if widget.resizeRadio.isChecked(): self.origrequest.targetSize = widget.resizeSpin.value() if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if self.origrequest.format.exists and \ self.origrequest.format.mountable and \ self.origrequest.format.mountpoint: if self.storage.formatByDefault(self.origrequest) and \ not queryNoFormatPreExisting(self.intf): continue # everything ok break
def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] raidmembers = [] if not rc: self.destroy() return [] widget = self.dialog.content for index in range(widget.raidMembers.count()): if widget.raidMembers.item(index).checkState() == Qt.Checked: raidmembers.append(widget.raidMembers.item(index).partition) # The user has to select some devices to be part of the array. if not raidmembers: continue mountpoint = str(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: self.intf.messageWindow(_("Mount Point Error"), msg, customIcon="error") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), customIcon="error") continue if not self.origrequest.exists: formatType = str(widget.filesystemMenu.currentText()) raidminor = widget.raidMinors.itemData(widget.raidMinors.currentIndex()).toInt()[0] raidlevel = widget.raidMinors.itemData(widget.raidLevels.currentIndex()).toInt()[0] if not raid.isRaid(raid.RAID0, raidlevel): spares = widget.spareSpin.value() else: spares = 0 format = formats.getFormat(formatType, mountpoint=mountpoint) members = len(raidmembers) - spares try: request = self.storage.newRaidArray(minor=raidminor, level=raidlevel, format=format, parents=raidmembers, totalDevices=len(raidmembers), memberDevices=members) except ValueError, e: self.intf.messageWindow(_("Error"), str(e), customIcon="error") continue if not self.isNew: # This may be handled in devicetree.registerAction, # but not in case when we change minor and thus # device name/path (at least with current md) operations.append(OperationDestroyDevice(self.origrequest)) operations.append(OperationCreateDevice(request)) operations.append(OperationCreateFormat(request)) else: format = None if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=self.origrequest.path) operations.append(OperationCreateFormat(self.origrequest, format)) else: cancel = [] cancel.extend(self.storage.devicetree.findOperations(type="destroy", object="format", devid=self.origrequest.id)) cancel.extend(self.storage.devicetree.findOperations(type="create", object="format", devid=self.origrequest.id)) for operation in cancel: devicetree.removeOperation(operation) self.origrequest.format = self.origrequest.originalFormat if self.origrequest.format.mountable: self.origrequest.format.mountpoint = mountpoint if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(self.origrequest)) if self.origrequest.format.exists and not format and \ self.storage.formatByDefault(self.origrequest): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break
def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: self.destroy() return [] widget = self.dialog.content mountpoint = unicode(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: ctx.interface.messageWindow(_("Mount Point Error"), msg, type="warning") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: ctx.interface.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint,), type="warning") continue if not self.origrequest.exists: if widget.primaryCheck.isChecked(): primary = True else: primary = None size = widget.sizeSpin.value() formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) if self.isNew: disk = self.storage.devicetree.getDeviceByPath(self.partedPartition.disk.device.path) else: disk = self.origrequest.disk err = doUIRAIDLVMChecks(format, [disk.name], self.storage) if err: self.intf.messageWindow(_("Error With Request"), err, type="error") continue weight = partitioning.weight(mountpoint=mountpoint, fstype=format.type) if self.isNew: request = self.storage.newPartition(size=size, grow=None, maxsize=0, primary=primary, format=format, parents=disk) else: request = self.origrequest request.weight = weight usedev = request if self.isNew: operations.append(OperationCreateDevice(request)) else: request.req_size = size request.req_base_size = size request.req_grow = None request.req_max_size = 0 request.req_primary = primary request.req_disks = [disk] operations.append(OperationCreateFormat(usedev, format)) else: # preexisting partition request = self.origrequest usedev = request origformat = usedev.format devicetree = self.storage.devicetree if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=usedev.path) operations.append(OperationCreateFormat(usedev, format)) else: cancel = [] cancel.extend(devicetree.findOperations(type="destroy", object="format", devid=request.id)) cancel.extend(devicetree.findOperations(type="create", object="format", devid=request.id)) cancel.reverse() for operation in cancel: devicetree.removeOperation(operation) request.format = request.originalFormat usedev = request if usedev.format.mountable: usedev.format.mountpoint = mountpoint if self.origrequest.protected and usedev.format.mountable: # users can set a mountpoint for protected partitions usedev.format.mountpoint = mountpoint request.weight = partitioning.weight(mountpoint=mountpoint, fstype=request.format.type) if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(usedev)) if widget.resizeRadio.isChecked(): size = widget.resizeSpin.value() try: operations.append(OperationResizeDevice(request, size)) if request.format.type and request.format.exists: operations.append(OperationResizeFormat(request, size)) except ValueError: pass if request.format.exists and \ getattr(request, "mountpoint", None) and \ self.storage.formatByDefault(request): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break return operations
def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: self.destroy() return [] widget = self.dialog.content mountpoint = unicode(widget.mountpointMenu.currentText()) active = widget.mountpointMenu.isEnabled() if active and mountpoint: msg = sanityCheckMountPoint(mountpoint) if msg: ctx.interface.messageWindow(_("Mount Point Error"), msg, type="warning") continue used = False for (mp, dev) in self.storage.mountpoints.iteritems(): if mp == mountpoint and \ dev.id != self.origrequest.id and \ not (self.origrequest.format.type == "luks" and self.origrequest in dev.parents): used = True break if used: ctx.interface.messageWindow( _("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % (mountpoint, ), type="warning") continue if not self.origrequest.exists: if widget.primaryCheck.isChecked(): primary = True else: primary = None size = widget.sizeSpin.value() formatType = str(widget.filesystemMenu.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint) if self.isNew: disk = self.storage.devicetree.getDeviceByPath( self.partedPartition.disk.device.path) else: disk = self.origrequest.disk err = doUIRAIDLVMChecks(format, [disk.name], self.storage) if err: self.intf.messageWindow(_("Error With Request"), err, type="error") continue weight = partitioning.weight(mountpoint=mountpoint, fstype=format.type) if self.isNew: request = self.storage.newPartition(size=size, grow=None, maxsize=0, primary=primary, format=format, parents=disk) else: request = self.origrequest request.weight = weight usedev = request if self.isNew: operations.append(OperationCreateDevice(request)) else: request.req_size = size request.req_base_size = size request.req_grow = None request.req_max_size = 0 request.req_primary = primary request.req_disks = [disk] operations.append(OperationCreateFormat(usedev, format)) else: # preexisting partition request = self.origrequest usedev = request origformat = usedev.format devicetree = self.storage.devicetree if widget.formatRadio.isChecked(): formatType = str(widget.formatCombo.currentText()) format = formats.getFormat(formatType, mountpoint=mountpoint, device=usedev.path) operations.append(OperationCreateFormat(usedev, format)) else: cancel = [] cancel.extend( devicetree.findOperations(type="destroy", object="format", devid=request.id)) cancel.extend( devicetree.findOperations(type="create", object="format", devid=request.id)) cancel.reverse() for operation in cancel: devicetree.removeOperation(operation) request.format = request.originalFormat usedev = request if usedev.format.mountable: usedev.format.mountpoint = mountpoint if self.origrequest.protected and usedev.format.mountable: # users can set a mountpoint for protected partitions usedev.format.mountpoint = mountpoint request.weight = partitioning.weight( mountpoint=mountpoint, fstype=request.format.type) if widget.migrateRadio.isChecked(): operations.append(OperationMigrateFormat(usedev)) if widget.resizeRadio.isChecked(): size = widget.resizeSpin.value() try: operations.append(OperationResizeDevice(request, size)) if request.format.type and request.format.exists: operations.append( OperationResizeFormat(request, size)) except ValueError: pass if request.format.exists and \ getattr(request, "mountpoint", None) and \ self.storage.formatByDefault(request): if not queryNoFormatPreExisting(self.intf): continue # everything ok, fall out of loop break return operations
def __init__(self, name, format=None, size=None, grow=False, maxsize=None, major=None, minor=None, bootable=None, sysfsPath='', parents=None, exists=None, partType=None, primary=False, weight=0): """ Create a Partition instance. Arguments: name -- the device name (generally a device node's basename) Keyword Arguments: exists -- indicates whether this is an existing device format -- the device's format (DeviceFormat instance) For existing partitions: parents -- the disk that contains this partition major -- the device major minor -- the device minor sysfsPath -- sysfs device path For new partitions: partType -- primary,extended,&c (as parted constant) grow -- whether or not to grow the partition maxsize -- max size for growable partitions (in MB) size -- the device's size (in MB) bootable -- whether the partition is bootable parents -- a list of potential containing disks weight -- an initial sorting weight to assign """ self.req_disks = [] self.req_partType = None self.req_primary = None self.req_grow = None self.req_bootable = None self.req_size = 0 self.req_base_size = 0 self.req_max_size = 0 self.req_base_weight = 0 self._bootable = False Device.__init__(self, name, format=format, size=size, major=major, minor=minor, exists=exists, sysfsPath=sysfsPath, parents=parents) if not exists: # this is a request, not a partition -- it has no parents self.req_disks = self.parents[:] for dev in self.parents: dev.removeChild() self.parents = [] # FIXME: Validate partType, but only if this is a new partition # Otherwise, overwrite it with the partition's type. self._partType = None self.partedFlags = {} self._partedPartition = None self._origPath = None self._currentSize = 0 # FIXME: Validate size, but only if this is a new partition. # For existing partitions we will get the size from # parted. if self.exists: ctx.logger.debug("looking up parted Partition: %s" % self.path) self._partedPartition = self.disk.format.partedDisk.getPartitionByPath(self.path) if not self._partedPartition: raise PartitionError("cannot find parted partition instance", self.name) self._origPath = self.path self.probe() if self.getFlag(parted.PARTITION_PREP): # the only way to identify a PPC PReP Boot partition is to # check the partition type/flags, so do it here. self.format = getFormat("prepboot", device=self.path, exists=True) else: # XXX It might be worthwhile to create a shit-simple # PartitionRequest class and pass one to this constructor # for new partitions. if not self._size: # default size for new partition requests self._size = self.defaultSize self.req_name = name self.req_partType = partType self.req_primary = primary self.req_max_size = numeric_type(maxsize) self.req_grow = grow self.req_bootable = bootable # req_size may be manipulated in the course of partitioning self.req_size = self._size # req_base_size will always remain constant self.req_base_size = self._size self.req_base_weight = weight
def __init__(self, name, format=None, size=None, grow=False, maxsize=None, major=None, minor=None, bootable=None, sysfsPath='', parents=None, exists=None, partType=None, primary=False, weight=0): """ Create a Partition instance. Arguments: name -- the device name (generally a device node's basename) Keyword Arguments: exists -- indicates whether this is an existing device format -- the device's format (DeviceFormat instance) For existing partitions: parents -- the disk that contains this partition major -- the device major minor -- the device minor sysfsPath -- sysfs device path For new partitions: partType -- primary,extended,&c (as parted constant) grow -- whether or not to grow the partition maxsize -- max size for growable partitions (in MB) size -- the device's size (in MB) bootable -- whether the partition is bootable parents -- a list of potential containing disks weight -- an initial sorting weight to assign """ self.req_disks = [] self.req_partType = None self.req_primary = None self.req_grow = None self.req_bootable = None self.req_size = 0 self.req_base_size = 0 self.req_max_size = 0 self.req_base_weight = 0 self._bootable = False Device.__init__(self, name, format=format, size=size, major=major, minor=minor, exists=exists, sysfsPath=sysfsPath, parents=parents) if not exists: # this is a request, not a partition -- it has no parents self.req_disks = self.parents[:] for dev in self.parents: dev.removeChild() self.parents = [] # FIXME: Validate partType, but only if this is a new partition # Otherwise, overwrite it with the partition's type. self._partType = None self.partedFlags = {} self._partedPartition = None self._origPath = None self._currentSize = 0 # FIXME: Validate size, but only if this is a new partition. # For existing partitions we will get the size from # parted. if self.exists: ctx.logger.debug("looking up parted Partition: %s" % self.path) self._partedPartition = self.disk.format.partedDisk.getPartitionByPath( self.path) if not self._partedPartition: raise PartitionError("cannot find parted partition instance", self.name) self._origPath = self.path self.probe() if self.getFlag(parted.PARTITION_PREP): # the only way to identify a PPC PReP Boot partition is to # check the partition type/flags, so do it here. self.format = getFormat("prepboot", device=self.path, exists=True) else: # XXX It might be worthwhile to create a shit-simple # PartitionRequest class and pass one to this constructor # for new partitions. if not self._size: # default size for new partition requests self._size = self.defaultSize self.req_name = name self.req_partType = partType self.req_primary = primary self.req_max_size = numeric_type(maxsize) self.req_grow = grow self.req_bootable = bootable # req_size may be manipulated in the course of partitioning self.req_size = self._size # req_base_size will always remain constant self.req_base_size = self._size self.req_base_weight = weight
def run(self): if self.dialog is None: return [] while 1: rc = self.dialog.exec_() operations = [] if not rc: if self.isNew: if self.lvs.has_key(self.origrequest.name): del self.lvs[self.origrequest.name] self.destroy() return [] widget = self.dialog.content name = str(widget.name.text()) pvs = widget.selectedPhysicalVolumes msg = sanityCheckVolumeGroupName(name) if msg: self.intf.messageWindow(_("Invalid Volume Group Name"), msg, type="warning") continue origname = self.origrequest.name if origname != name: if name in [vg.name for vg in self.storage.vgs]: self.intf.messageWindow(_("Name in use"), _("The volume group name \"%s\" is " "already in use. Please pick another.") % (name,), type="warning") continue peSize = int(widget.physicalExtends.itemData(widget.physicalExtends.currentIndex())) / 1024.0 origlvs = self.origrequest.lvs if not self.origrequest.exists: ctx.logger.debug("non-existing vg -- setting up lvs, pvs, name, peSize") for lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) for pv in self.origrequest.pvs: if pv not in self.pvs: self.origrequest._removePhysicalVolume(pv) for pv in self.pvs: if pv not in self.origrequest.pvs: self.origrequest._addPhysicalVolume(pv) self.origrequest.name = name self.origrequest.peSize = peSize if self.isNew: operations = [OperationCreateDevice(self.origrequest)] for lv in origlvs: ctx.logger.debug("old lv %s..." % lv.lvname) if not lv.exists or lv.lvname not in self.lvs or \ (not self.lvs[lv.lvname]['exists'] and lv.exists): ctx.logger.debug("removing lv %s" % lv.lvname) if lv.format.type: operations.append(OperationDestroyFormat(lv)) if lv in self.origrequest.lvs: self.origrequest._removeLogicalVolume(lv) operations.append(OperationDestroyDevice(lv)) # schedule creation of all new lvs, their formats, luks devices, &c tempvg = widget.tmpVolumeGroup for lv in tempvg.lvs: ctx.logger.debug("new lv %s" % lv) if not lv.exists: ctx.logger.debug("creating lv %s" % lv.lvname) logicalvolume = LogicalVolume(lv.lvname, self.origrequest, size=lv.size) operations.append(OperationCreateDevice(logicalvolume)) # create the format mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=logicalvolume.path) operations.append(OperationCreateFormat(logicalvolume, format)) else: ctx.logger.debug("lv %s already exists" % lv.lvname) origlv = widget.getLogicalVolumeByName(lv.lvname) if lv.resizable and lv.targetSize != origlv.size: operations.append(OperationResizeDevice(origlv, lv.targetSize)) if lv.format.exists: ctx.logger.debug("format already exists") usedev = origlv format = lv.format if format == usedev.originalFormat: cancel = [] cancel.extend(self.parent.storage.devicetree.findOperations(type="create", object="format", devid=origlv.id)) cancel.extend(self.parent.storage.devicetree.findOperations(type="destroy", object="format", devid=origlv.id)) for operation in cancel: self.storage.devicetree.cancelOperation(operation) if hasattr(format, "mountpoint"): usedev.format.mountpoint = format.mountpoint if format.migratable and format.migrate and \ not usedev.format.migrate: usedev.format.migrate = format.migrate operations.append(OperationMigrateFormat(usedev)) if format.resizable and lv.format.resizable and \ lv.targetSize != format.targetSize and \ lv.targetSize != lv.currentSize and \ usedev.format.exists: ctx.logger.debug("resizing format on %s to %d" % (usedev.lvname, lv.targetSize)) operations.append(OperationResizeFormat(usedev, lv.targetSize)) elif lv.format.type: ctx.logger.debug("new format: %s" % lv.format.type) if origlv.format.type: operations.append(OperationDestroyFormat(origlv)) mountpoint = getattr(lv.format, "mountpoint", None) format = formats.getFormat(lv.format.type, mountpoint=mountpoint, device=origlv.path) operations.append(OperationCreateFormat(origlv, format)) else: ctx.logger.debug("no format!") break return operations
def mountPointChanged(self, index): if yali.util.isEfi() and self.mountpointMenu.itemText(index) == "/boot/efi": self.filesystemMenu.setCurrentText(self.filesystemMenu.findText(formats.getFormat("efi").name)) elif self.mountpointMenu.itemText(index) == "/boot": self.filesystemMenu.setCurrentText(self.filesystemMenu.findText(formats.get_default_filesystem_type(boot=True)))
def updateMenus(self): self.createPartition.setVisible(True) activatePartition = False try: freePartition = hasFreeDiskSpace(self.storage) except AttributeError, msg: ctx.logger.debug(msg) else: if freePartition: activatePartition = True activateVolumeGroup = False availablePVS = len(self.storage.unusedPVS()) if (lvm.has_lvm() and formats.getFormat("lvmpv").supported and availablePVS > 0): activateVolumeGroup = True activateRaidArray = False availableRaidMembers = len(self.storage.unusedRaidMembers()) availableMinors = len(self.storage.unusedRaidMinors) if (availableMinors > 0 and formats.getFormat("mdmember").supported and availableRaidMembers > 1): activateRaidArray = True """if (not activatePartition and not activateVolumeGroup): self.intf.messageWindow(_("Cannot perform any creation operation"), _("Note that the creation operation requires one of the\nfollowing:" " * Free space in one of the Hard Drives.\n" " * At least one free physical volume (LVM) partition.\n" " * At least one Volume Group with free space."),