aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'partIntfHelpers.py')
-rw-r--r--partIntfHelpers.py354
1 files changed, 354 insertions, 0 deletions
diff --git a/partIntfHelpers.py b/partIntfHelpers.py
new file mode 100644
index 0000000..3aaba71
--- /dev/null
+++ b/partIntfHelpers.py
@@ -0,0 +1,354 @@
+#
+# partIntfHelpers.py: partitioning interface helper functions
+#
+# Copyright (C) 2002 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Matt Wilson <msw@redhat.com>
+# Jeremy Katz <katzj@redhat.com>
+# Mike Fulbright <msf@redhat.com>
+# Harald Hoyer <harald@redhat.de>
+#
+
+"""Helper functions shared between partitioning interfaces."""
+
+import string
+from constants import *
+import parted
+import iutil
+from storage.formats import getFormat
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+def sanityCheckVolumeGroupName(volname):
+ """Make sure that the volume group name doesn't contain invalid chars."""
+ badNames = ['lvm', 'root', '.', '..' ]
+
+ if not volname:
+ return _("Please enter a volume group name.")
+
+ # ripped the value for this out of linux/include/lvm.h
+ if len(volname) > 128:
+ return _("Volume Group Names must be less than 128 characters")
+
+ if volname in badNames:
+ return _("Error - the volume group name %s is not valid." % (volname,))
+
+ for i in range(0, len(volname)):
+ rc = string.find(string.letters + string.digits + '.' + '_' + '-', volname[i])
+ if rc == -1:
+ return _("Error - the volume group name contains illegal "
+ "characters or spaces. Acceptable characters "
+ "are letters, digits, '.' or '_'.")
+ return None
+
+def sanityCheckLogicalVolumeName(logvolname):
+ """Make sure that the logical volume name doesn't contain invalid chars."""
+ badNames = ['group', '.', '..' ]
+
+ if not logvolname:
+ return _("Please enter a logical volume name.")
+
+ # ripped the value for this out of linux/include/lvm.h
+ if len(logvolname) > 128:
+ return _("Logical Volume Names must be less than 128 characters")
+
+
+ if logvolname in badNames:
+ return _("Error - the logical volume name %s is not "
+ "valid." % (logvolname,))
+
+ for i in range(0, len(logvolname)):
+ rc = string.find(string.letters + string.digits + '.' + '_', logvolname[i])
+ if rc == -1:
+ return _("Error - the logical volume name contains illegal "
+ "characters or spaces. Acceptable characters "
+ "are letters, digits, '.' or '_'.")
+ return None
+
+def sanityCheckMountPoint(mntpt, fstype, preexisting, format):
+ """Sanity check that the mountpoint is valid.
+
+ mntpt is the mountpoint being used.
+ fstype is the file system being used on the request.
+ preexisting is whether the request was preexisting (request.preexist)
+ format is whether the request is being formatted or not
+ """
+ if mntpt:
+ passed = 1
+ if not mntpt:
+ passed = 0
+ else:
+ if mntpt[0] != '/' or (len(mntpt) > 1 and mntpt[-1:] == '/'):
+ passed = 0
+ elif mntpt.find(' ') > -1:
+ passed = 0
+
+ if not passed:
+ return _("The mount point %s is invalid. Mount points must start "
+ "with '/' and cannot end with '/', and must contain "
+ "printable characters and no spaces." % mntpt)
+ else:
+ return None
+ else:
+ if (fstype and fstype.mountable and (not preexisting or format)):
+ return _("Please specify a mount point for this partition.")
+ else:
+ # its an existing partition so don't force a mount point
+ return None
+
+def doDeleteDevice(intf, storage, device, confirm=1, quiet=0):
+ """Delete a partition from the request list.
+
+ intf is the interface
+ storage is the storage instance
+ device is the device to delete
+ """
+ if not device:
+ intf.messageWindow(_("Unable To Delete"),
+ _("You must first select a partition to delete."),
+ custom_icon="error")
+ return False
+
+ reason = storage.deviceImmutable(device)
+ if reason:
+ intf.messageWindow(_("Unable To Delete"),
+ reason,
+ custom_icon="error")
+ return False
+
+ if confirm and not confirmDelete(intf, device):
+ return False
+
+ deps = storage.deviceDeps(device)
+ while deps:
+ leaves = [d for d in deps if d.isleaf]
+ for leaf in leaves:
+ storage.destroyDevice(leaf)
+ deps.remove(leaf)
+
+ storage.destroyDevice(device)
+ return True
+
+def doClearPartitionedDevice(intf, storage, device, confirm=1, quiet=0):
+ """ Remove all devices/partitions currently on device.
+
+ device -- a partitioned device such as a disk
+
+ """
+ if confirm:
+ rc = intf.messageWindow(_("Confirm Delete"),
+ _("You are about to delete all partitions on "
+ "the device '%s'.") % (device.path,),
+ type="custom", custom_icon="warning",
+ custom_buttons=[_("Cancel"), _("_Delete")])
+
+ if not rc:
+ return False
+
+ immutable = []
+ partitions = [p for p in storage.partitions if p.disk == device]
+ if not partitions:
+ return False
+
+ partitions.sort(key=lambda p: p.partedPartition.number, reverse=True)
+ for p in partitions:
+ deps = storage.deviceDeps(p)
+ clean = True # true if part and its deps were removed
+ while deps:
+ leaves = [d for d in deps if d.isleaf]
+ for leaf in leaves:
+ if leaf in immutable:
+ # this device was removed from deps at the same time it
+ # was added to immutable, so it won't appear in leaves
+ # in the next iteration
+ continue
+
+ if storage.deviceImmutable(leaf):
+ immutable.append(leaf)
+ for dep in [d for d in deps if d != leaf]:
+ # mark devices this device depends on as immutable
+ # to prevent getting stuck with non-leaf deps
+ # protected by immutable leaf devices
+ if leaf.dependsOn(dep):
+ deps.remove(dep)
+ if dep not in immutable:
+ immutable.append(dep)
+ clean = False
+ else:
+ storage.destroyDevice(leaf)
+ deps.remove(leaf)
+
+ if storage.deviceImmutable(p):
+ immutable.append(p)
+ clean = False
+
+ if clean:
+ storage.destroyDevice(p)
+
+ if immutable and not quiet:
+ remaining = "\t" + "\n\t".join(p.path for p in immutable) + "\n"
+ intf.messageWindow(_("Notice"),
+ _("The following partitions were not deleted "
+ "because they are in use:\n\n%s") % remaining,
+ custom_icon="warning")
+
+ return True
+
+def checkForSwapNoMatch(anaconda):
+ """Check for any partitions of type 0x82 which don't have a swap fs."""
+ for device in anaconda.storage.partitions:
+ if not device.exists:
+ # this is only for existing partitions
+ continue
+
+ if device.getFlag(parted.PARTITION_SWAP) and \
+ not device.format.type == "swap":
+ rc = anaconda.intf.messageWindow(_("Format as Swap?"),
+ _("%s has a partition type of 0x82 "
+ "(Linux swap) but does not appear to "
+ "be formatted as a Linux swap "
+ "partition.\n\n"
+ "Would you like to format this "
+ "partition as a swap partition?")
+ % device.path, type = "yesno",
+ custom_icon="question")
+ if rc == 1:
+ format = getFormat("swap", device=device.path)
+ anaconda.storage.formatDevice(device, format)
+
+ return
+
+def mustHaveSelectedDrive(intf):
+ txt =_("You need to select at least one hard drive to install %s.") % (productName,)
+ intf.messageWindow(_("Error"), txt, custom_icon="error")
+
+def queryNoFormatPreExisting(intf):
+ """Ensure the user wants to use a partition without formatting."""
+ txt = _("You have chosen to use a pre-existing "
+ "partition for this installation without formatting it. "
+ "We recommend that you format this partition "
+ "to make sure files from a previous operating system installation "
+ "do not cause problems with this installation of Linux. "
+ "However, if this partition contains files that you need "
+ "to keep, such as home directories, then "
+ "continue without formatting this partition.")
+ rc = intf.messageWindow(_("Format?"), txt, type = "custom", custom_buttons=[_("_Modify Partition"), _("Do _Not Format")], custom_icon="warning")
+ return rc
+
+def partitionSanityErrors(intf, errors):
+ """Errors were found sanity checking. Tell the user they must fix."""
+ rc = 1
+ if errors:
+ errorstr = string.join(errors, "\n\n")
+ rc = intf.messageWindow(_("Error with Partitioning"),
+ _("The following critical errors exist "
+ "with your requested partitioning "
+ "scheme. "
+ "These errors must be corrected prior "
+ "to continuing with your install of "
+ "%(productName)s.\n\n%(errorstr)s") \
+ % {'productName': productName,
+ 'errorstr': errorstr},
+ custom_icon="error")
+ return rc
+
+def partitionSanityWarnings(intf, warnings):
+ """Sanity check found warnings. Make sure the user wants to continue."""
+ rc = 1
+ if warnings:
+ warningstr = string.join(warnings, "\n\n")
+ rc = intf.messageWindow(_("Partitioning Warning"),
+ _("The following warnings exist with "
+ "your requested partition scheme.\n\n%s"
+ "\n\nWould you like to continue with "
+ "your requested partitioning "
+ "scheme?") % (warningstr),
+ type="yesno", custom_icon="warning")
+ return rc
+
+
+def partitionPreExistFormatWarnings(intf, warnings):
+ """Double check that preexistings being formatted are fine."""
+ rc = 1
+ if warnings:
+
+ labelstr1 = _("The following pre-existing partitions have been "
+ "selected to be formatted, destroying all data.")
+
+ labelstr2 = _("Select 'Yes' to continue and format these "
+ "partitions, or 'No' to go back and change these "
+ "settings.")
+ commentstr = ""
+ for (dev, type, mntpt) in warnings:
+ commentstr = commentstr + "/dev/%s %s %s\n" % (dev,type,mntpt)
+ rc = intf.messageWindow(_("Format Warning"), "%s\n\n%s\n\n%s" %
+ (labelstr1, labelstr2, commentstr),
+ type="yesno", custom_icon="warning")
+ return rc
+
+def getPreExistFormatWarnings(storage):
+ """Return a list of preexisting devices being formatted."""
+ devices = []
+ for device in storage.devicetree.devices:
+ if device.exists and not device.format.exists and \
+ not device.format.hidden:
+ devices.append(device)
+
+ devices.sort(key=lambda d: d.name)
+ rc = []
+ for device in devices:
+ rc.append((device.path,
+ device.format.name,
+ getattr(device.format, "mountpoint", "")))
+ return rc
+
+def confirmDelete(intf, device):
+ """Confirm the deletion of a device."""
+ if not device:
+ return
+
+ if device.type == "lvmvg":
+ errmsg = (_("You are about to delete the volume group \"%s\"."
+ "\n\nALL logical volumes in this volume group "
+ "will be lost!") % device.name)
+ elif device.type == "lvmlv":
+ errmsg = (_("You are about to delete the logical volume \"%s\".")
+ % device.name)
+ elif device.type == "mdarray":
+ errmsg = _("You are about to delete a RAID device.")
+ elif device.type == "partition":
+ errmsg = (_("You are about to delete the %s partition.")
+ % device.path)
+ else:
+ # we may want something a little bit prettier than device.type
+ errmsg = (_("You are about to delete the %(type)s %(name)s") \
+ % {'type': device.type, 'name': device.name})
+
+ rc = intf.messageWindow(_("Confirm Delete"), errmsg, type="custom",
+ custom_buttons=[_("Cancel"), _("_Delete")],
+ custom_icon="question")
+
+ return rc
+
+def confirmResetPartitionState(intf):
+ """Confirm reset of partitioning to that present on the system."""
+ rc = intf.messageWindow(_("Confirm Reset"),
+ _("Are you sure you want to reset the "
+ "partition table to its original state?"),
+ type="yesno", custom_icon="question")
+ return rc
+