diff options
Diffstat (limited to 'pyanaconda/storage/formats')
-rw-r--r-- | pyanaconda/storage/formats/Makefile.am | 24 | ||||
-rw-r--r-- | pyanaconda/storage/formats/__init__.py | 438 | ||||
-rw-r--r-- | pyanaconda/storage/formats/biosboot.py | 60 | ||||
-rw-r--r-- | pyanaconda/storage/formats/disklabel.py | 443 | ||||
-rw-r--r-- | pyanaconda/storage/formats/dmraid.py | 114 | ||||
-rw-r--r-- | pyanaconda/storage/formats/fs.py | 1433 | ||||
-rw-r--r-- | pyanaconda/storage/formats/luks.py | 342 | ||||
-rw-r--r-- | pyanaconda/storage/formats/lvmpv.py | 146 | ||||
-rw-r--r-- | pyanaconda/storage/formats/mdraid.py | 120 | ||||
-rw-r--r-- | pyanaconda/storage/formats/multipath.py | 94 | ||||
-rw-r--r-- | pyanaconda/storage/formats/prepboot.py | 87 | ||||
-rw-r--r-- | pyanaconda/storage/formats/swap.py | 171 |
12 files changed, 0 insertions, 3472 deletions
diff --git a/pyanaconda/storage/formats/Makefile.am b/pyanaconda/storage/formats/Makefile.am deleted file mode 100644 index 7ecaf075d..000000000 --- a/pyanaconda/storage/formats/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -# storage/formats/Makefile.am for anaconda -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Author: David Cantrell <dcantrell@redhat.com> - -pkgpyexecdir = $(pyexecdir)/py$(PACKAGE_NAME) -storageformatsdir = $(pkgpyexecdir)/storage/formats -storageformats_PYTHON = *.py - -MAINTAINERCLEANFILES = Makefile.in diff --git a/pyanaconda/storage/formats/__init__.py b/pyanaconda/storage/formats/__init__.py deleted file mode 100644 index 62bfb31c4..000000000 --- a/pyanaconda/storage/formats/__init__.py +++ /dev/null @@ -1,438 +0,0 @@ -# __init__.py -# Entry point for anaconda storage formats subpackage. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -import os - -from pyanaconda.product import productName -from pyanaconda.baseudev import udev_get_device -from ..util import notify_kernel -from ..util import get_sysfs_path_by_name -from ..util import run_program -from ..storage_log import log_method_call -from ..errors import * -from ..devicelibs.dm import dm_node_from_name -from ..devicelibs.mdraid import md_node_from_name -from ..udev import udev_device_get_major, udev_device_get_minor - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - - -device_formats = {} -def register_device_format(fmt_class): - if not issubclass(fmt_class, DeviceFormat): - raise ValueError("arg1 must be a subclass of DeviceFormat") - - device_formats[fmt_class._type] = fmt_class - log.debug("registered device format class %s as %s" % (fmt_class.__name__, - fmt_class._type)) - -default_fstypes = ["ext4", "ext3", "ext2"] -if productName.startswith("Red Hat Enterprise Linux"): - default_fstypes.insert(0, "xfs") - -def get_default_filesystem_type(): - for fstype in default_fstypes: - try: - supported = get_device_format_class(fstype).supported - except AttributeError: - supported = None - - if supported: - return fstype - - raise DeviceFormatError("None of %s is supported by your kernel" % ",".join(default_fstypes)) - -def getFormat(fmt_type, *args, **kwargs): - """ Return a DeviceFormat instance based on fmt_type and args. - - Given a device format type and a set of constructor arguments, - return a DeviceFormat instance. - - Return None if no suitable format class is found. - - Arguments: - - fmt_type -- the name of the format type (eg: 'ext3', 'swap') - - Keyword Arguments: - - The keyword arguments may vary according to the format type, - but here is the common set: - - device -- path to the device on which the format resides - uuid -- the UUID of the (preexisting) formatted device - exists -- whether or not the format exists on the device - - """ - fmt_class = get_device_format_class(fmt_type) - fmt = None - if fmt_class: - fmt = fmt_class(*args, **kwargs) - try: - className = fmt.__class__.__name__ - except AttributeError: - className = None - log.debug("getFormat('%s') returning %s instance" % (fmt_type, className)) - return fmt - -def collect_device_format_classes(): - """ Pick up all device format classes from this directory. - - Note: Modules must call register_device_format(FormatClass) in - order for the format class to be picked up. - """ - dir = os.path.dirname(__file__) - for module_file in os.listdir(dir): - # make sure we're not importing this module - if module_file.endswith(".py") and module_file != __file__: - mod_name = module_file[:-3] - # imputil is deprecated in python 2.6 - try: - globals()[mod_name] = __import__(mod_name, globals(), locals(), [], -1) - except ImportError: - log.error("import of device format module '%s' failed" % mod_name) - from traceback import format_exc - log.debug(format_exc()) - -def get_device_format_class(fmt_type): - """ Return an appropriate format class based on fmt_type. """ - if not device_formats: - collect_device_format_classes() - - fmt = device_formats.get(fmt_type) - if not fmt: - for fmt_class in device_formats.values(): - if fmt_type and fmt_type == fmt_class._name: - fmt = fmt_class - break - elif fmt_type in fmt_class._udevTypes: - fmt = fmt_class - break - - # default to no formatting, AKA "Unknown" - if not fmt: - fmt = DeviceFormat - - return fmt - -class DeviceFormat(object): - """ Generic device format. """ - _type = None - _name = "Unknown" - _udevTypes = [] - partedFlag = None - partedSystem = None - _formattable = False # can be formatted - _supported = False # is supported - _linuxNative = False # for clearpart - _packages = [] # required packages - _services = [] # required services - _resizable = False # can be resized - _maxSize = 0 # maximum size in MB - _minSize = 0 # minimum size in MB - _dump = False - _check = False - _hidden = False # hide devices with this formatting? - - def __init__(self, *args, **kwargs): - """ Create a DeviceFormat instance. - - Keyword Arguments: - - device -- path to the underlying device - uuid -- this format's UUID - exists -- indicates whether this is an existing format - - """ - self.device = kwargs.get("device") - self.uuid = kwargs.get("uuid") - self.exists = kwargs.get("exists") - self.options = kwargs.get("options") - self._majorminor = None - - # don't worry about existence if this is a DeviceFormat instance - #if self.__class__ is DeviceFormat: - # self.exists = True - - def __repr__(self): - s = ("%(classname)s instance (%(id)s) --\n" - " type = %(type)s name = %(name)s status = %(status)s\n" - " device = %(device)s uuid = %(uuid)s exists = %(exists)s\n" - " options = %(options)s supported = %(supported)s" - " formattable = %(format)s resizable = %(resize)s\n" % - {"classname": self.__class__.__name__, "id": "%#x" % id(self), - "type": self.type, "name": self.name, "status": self.status, - "device": self.device, "uuid": self.uuid, "exists": self.exists, - "options": self.options, "supported": self.supported, - "format": self.formattable, "resize": self.resizable}) - return s - - @property - def _existence_str(self): - exist = "existing" - if not self.exists: - exist = "non-existent" - return exist - - @property - def desc(self): - return str(self.type) - - def __str__(self): - return "%s %s" % (self._existence_str, self.desc) - - @property - def dict(self): - d = {"type": self.type, "name": self.name, "device": self.device, - "uuid": self.uuid, "exists": self.exists, - "options": self.options, "supported": self.supported, - "resizable": self.resizable} - return d - - def _setOptions(self, options): - self._options = options - - def _getOptions(self): - return self._options - - options = property(_getOptions, _setOptions) - - def _setDevice(self, devspec): - if devspec and not devspec.startswith("/"): - raise ValueError("device must be a fully qualified path") - self._device = devspec - - def _getDevice(self): - return self._device - - device = property(lambda f: f._getDevice(), - lambda f,d: f._setDevice(d), - doc="Full path the device this format occupies") - - @property - def name(self): - if self._name: - name = self._name - else: - name = self.type - return name - - @property - def type(self): - return self._type - - def probe(self): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - - def notifyKernel(self): - log_method_call(self, device=self.device, - type=self.type) - if not self.device: - return - - if self.device.startswith("/dev/mapper/"): - try: - name = dm_node_from_name(os.path.basename(self.device)) - except DMError: - log.warning("failed to get dm node for %s" % self.device) - return - elif self.device.startswith("/dev/md/"): - try: - name = md_node_from_name(os.path.basename(self.device)) - except MDRaidError: - log.warning("failed to get md node for %s" % self.device) - return - else: - name = self.device - - path = get_sysfs_path_by_name(name) - try: - notify_kernel(path, action="change") - except (ValueError, IOError) as e: - log.warning("failed to notify kernel of change: %s" % e) - - def cacheMajorminor(self): - """ Cache the value of self.majorminor. - - Once a device node of this format's device disappears (for instance - after a teardown), it is no longer possible to figure out the value - of self.majorminor pseudo-unique string. Call this method before - that happens for caching this. - """ - self._majorminor = None - try: - self.majorminor # this does the caching - except StorageError: - # entirely possible there's no majorminor, for instance an - # LVMVolumeGroup has got no device node and no sysfs path. In this - # case obviously, calling majorminor of this object later raises an - # exception. - pass - return self._majorminor - - def create(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - # allow late specification of device path - device = kwargs.get("device") - if device: - self.device = device - - if not os.path.exists(self.device): - raise FormatCreateError("invalid device specification", self.device) - - def destroy(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - try: - rc = run_program(["wipefs", "-a", self.device]) - except OSError as e: - err = str(e) - else: - err = "" - if rc: - err = str(rc) - - if err: - msg = "error wiping old signatures from %s: %s" % (self.device, err) - raise FormatDestroyError(msg) - - self.exists = False - - def setup(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - - if not self.exists: - raise FormatSetupError("format has not been created") - - if self.status: - return - - # allow late specification of device path - device = kwargs.get("device") - if device: - self.device = device - - if not self.device or not os.path.exists(self.device): - raise FormatSetupError("invalid device specification") - - def teardown(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - - @property - def status(self): - return (self.exists and - self.__class__ is not DeviceFormat and - isinstance(self.device, str) and - self.device and - os.path.exists(self.device)) - - @property - def formattable(self): - """ Can we create formats of this type? """ - return self._formattable - - @property - def supported(self): - """ Is this format a supported type? """ - return self._supported - - @property - def packages(self): - """ Packages required to manage formats of this type. """ - return self._packages - - @property - def services(self): - """ Services required to manage formats of this type. """ - return self._services - - @property - def resizable(self): - """ Can formats of this type be resized? """ - return self._resizable and self.exists - - @property - def linuxNative(self): - """ Is this format type native to linux? """ - return self._linuxNative - - @property - def mountable(self): - """ Is this something we can mount? """ - return False - - @property - def dump(self): - """ Whether or not this format will be dumped by dump(8). """ - return self._dump - - @property - def check(self): - """ Whether or not this format is checked on boot. """ - return self._check - - @property - def maxSize(self): - """ Maximum size (in MB) for this format type. """ - return self._maxSize - - @property - def minSize(self): - """ Minimum size (in MB) for this format type. """ - return self._minSize - - @property - def hidden(self): - """ Whether devices with this formatting should be hidden in UIs. """ - return self._hidden - - @property - def majorminor(self): - """A string suitable for using as a pseudo-unique ID in kickstart.""" - if not self._majorminor: - # If this is a device-mapper device, we have to get the DM node and - # build the sysfs path from that. - try: - device = dm_node_from_name(os.path.basename(self.device)) - except DMError: - device = self.device - - try: - sysfs_path = get_sysfs_path_by_name(device) - except RuntimeError: - raise StorageError("DeviceFormat.majorminor: " - "can not get majorminor for '%s'" % device) - dev = udev_get_device(sysfs_path[4:]) - - self._majorminor = "%03d%03d" %\ - (udev_device_get_major(dev), udev_device_get_minor(dev)) - return self._majorminor - -collect_device_format_classes() diff --git a/pyanaconda/storage/formats/biosboot.py b/pyanaconda/storage/formats/biosboot.py deleted file mode 100644 index c3aef8d2b..000000000 --- a/pyanaconda/storage/formats/biosboot.py +++ /dev/null @@ -1,60 +0,0 @@ -# biosboot.py -# Device format classes for anaconda's storage configuration module. -# -# Copyright (C) 2011 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -from parted import PARTITION_BIOS_GRUB - -from ..errors import * -from .. import platform -from . import DeviceFormat, register_device_format - -class BIOSBoot(DeviceFormat): - """ BIOS boot partition for GPT disklabels. """ - _type = "biosboot" - _name = "BIOS Boot" - _udevTypes = [] - partedFlag = PARTITION_BIOS_GRUB - _formattable = True # can be formatted - _linuxNative = True # for clearpart - _maxSize = 2 # maximum size in MB - _minSize = 0.5 # minimum size in MB - - def __init__(self, *args, **kwargs): - """ Create a BIOSBoot instance. - - Keyword Arguments: - - device -- path to the underlying device - exists -- indicates whether this is an existing format - - """ - DeviceFormat.__init__(self, *args, **kwargs) - - @property - def status(self): - return False - - @property - def supported(self): - return isinstance(platform.platform, platform.X86) - -register_device_format(BIOSBoot) - diff --git a/pyanaconda/storage/formats/disklabel.py b/pyanaconda/storage/formats/disklabel.py deleted file mode 100644 index 018adf426..000000000 --- a/pyanaconda/storage/formats/disklabel.py +++ /dev/null @@ -1,443 +0,0 @@ -# disklabel.py -# Device format classes for anaconda's storage configuration module. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -import os -import copy - -from ..storage_log import log_method_call -import parted -import _ped -from ..errors import * -from .. import arch -from ..flags import flags -from ..udev import udev_settle -from . import DeviceFormat, register_device_format - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - - -class DiskLabel(DeviceFormat): - """ Disklabel """ - _type = "disklabel" - _name = "partition table" - _formattable = True # can be formatted - _supported = False # is supported - - def __init__(self, *args, **kwargs): - """ Create a DiskLabel instance. - - Keyword Arguments: - - labelType -- type of disklabel to create - device -- path to the underlying device - exists -- indicates whether this is an existing format - - """ - log_method_call(self, *args, **kwargs) - DeviceFormat.__init__(self, *args, **kwargs) - - if not self.exists: - self._labelType = kwargs.get("labelType", "msdos") - else: - self._labelType = "" - - self._size = None - - self._partedDevice = None - self._partedDisk = None - self._origPartedDisk = None - self._alignment = None - self._endAlignment = None - - if self.partedDevice: - # set up the parted objects and raise exception on failure - self._origPartedDisk = self.partedDisk.duplicate() - - def __deepcopy__(self, memo): - """ Create a deep copy of a Disklabel instance. - - We can't do copy.deepcopy on parted objects, which is okay. - For these parted objects, we just do a shallow copy. - """ - new = self.__class__.__new__(self.__class__) - memo[id(self)] = new - shallow_copy_attrs = ('_partedDevice', '_alignment', '_endAlignment') - duplicate_attrs = ('_partedDisk', '_origPartedDisk') - for (attr, value) in self.__dict__.items(): - if attr in shallow_copy_attrs: - setattr(new, attr, copy.copy(value)) - elif attr in duplicate_attrs: - setattr(new, attr, value.duplicate()) - else: - setattr(new, attr, copy.deepcopy(value, memo)) - - return new - - def __repr__(self): - s = DeviceFormat.__repr__(self) - if flags.testing: - return s - s += (" type = %(type)s partition count = %(count)s" - " sectorSize = %(sectorSize)s\n" - " align_offset = %(offset)s align_grain = %(grain)s\n" - " partedDisk = %(disk)s\n" - " origPartedDisk = %(orig_disk)r\n" - " partedDevice = %(dev)s\n" % - {"type": self.labelType, "count": len(self.partitions), - "sectorSize": self.partedDevice.sectorSize, - "offset": self.alignment.offset, - "grain": self.alignment.grainSize, - "disk": self.partedDisk, "orig_disk": self._origPartedDisk, - "dev": self.partedDevice}) - return s - - @property - def desc(self): - return "%s %s" % (self.labelType, self.type) - - @property - def dict(self): - d = super(DiskLabel, self).dict - if flags.testing: - return d - - d.update({"labelType": self.labelType, - "partitionCount": len(self.partitions), - "sectorSize": self.partedDevice.sectorSize, - "offset": self.alignment.offset, - "grainSize": self.alignment.grainSize}) - return d - - def resetPartedDisk(self): - """ Set this instance's partedDisk to reflect the disk's contents. """ - log_method_call(self, device=self.device) - self._partedDisk = self._origPartedDisk - - def freshPartedDisk(self): - """ Return a new, empty parted.Disk instance for this device. """ - log_method_call(self, device=self.device, labelType=self._labelType) - return parted.freshDisk(device=self.partedDevice, ty=self._labelType) - - @property - def partedDisk(self): - if not self._partedDisk: - if self.exists: - try: - self._partedDisk = parted.Disk(device=self.partedDevice) - except (_ped.DiskLabelException, _ped.IOException, - NotImplementedError) as e: - raise InvalidDiskLabelError() - - if self._partedDisk.type == "loop": - # When the device has no partition table but it has a FS, - # it will be created with label type loop. Treat the - # same as if the device had no label (cause it really - # doesn't). - raise InvalidDiskLabelError() - - # here's where we correct the ctor-supplied disklabel type for - # preexisting disklabels if the passed type was wrong - self._labelType = self._partedDisk.type - else: - self._partedDisk = self.freshPartedDisk() - - # turn off cylinder alignment - if self._partedDisk.isFlagAvailable(parted.DISK_CYLINDER_ALIGNMENT): - self._partedDisk.unsetFlag(parted.DISK_CYLINDER_ALIGNMENT) - - # Set the boot flag on the GPT PMBR, this helps some BIOS systems boot - if self._partedDisk.isFlagAvailable(parted.DISK_GPT_PMBR_BOOT): - # MAC can boot as EFI or as BIOS, neither should have PMBR boot set - if arch.isEfi() or arch.isMactel(): - self._partedDisk.unsetFlag(parted.DISK_GPT_PMBR_BOOT) - log.debug("Clear pmbr_boot on %s" % (self._partedDisk,)) - else: - self._partedDisk.setFlag(parted.DISK_GPT_PMBR_BOOT) - log.debug("Set pmbr_boot on %s" % (self._partedDisk,)) - else: - log.debug("Did not change pmbr_boot on %s" % (self._partedDisk,)) - - return self._partedDisk - - @property - def partedDevice(self): - if not self._partedDevice and self.device: - if os.path.exists(self.device): - # We aren't guaranteed to be able to get a device. In - # particular, built-in USB flash readers show up as devices but - # do not always have any media present, so parted won't be able - # to find a device. - try: - self._partedDevice = parted.Device(path=self.device) - except (_ped.IOException, _ped.DeviceException) as e: - log.error("DiskLabel.partedDevice: Parted exception: %s" % e) - else: - log.info("DiskLabel.partedDevice: %s does not exist" % self.device) - - if not self._partedDevice: - log.info("DiskLabel.partedDevice returning None") - return self._partedDevice - - @property - def labelType(self): - """ The disklabel type (eg: 'gpt', 'msdos') """ - try: - lt = self.partedDisk.type - except Exception: - lt = self._labelType - return lt - - @property - def name(self): - return "%s (%s)" % (self._name, self.labelType.upper()) - - @property - def size(self): - size = self._size - if not size: - try: - size = self.partedDevice.getSize(unit="MB") - except Exception: - size = 0 - - return size - - @property - def status(self): - """ Device status. """ - return False - - def setup(self, *args, **kwargs): - """ Open, or set up, a device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise DeviceFormatError("format has not been created") - - if self.status: - return - - DeviceFormat.setup(self, *args, **kwargs) - - def teardown(self, *args, **kwargs): - """ Close, or tear down, a device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise DeviceFormatError("format has not been created") - - def create(self, *args, **kwargs): - """ Create the device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if self.exists: - raise DeviceFormatError("format already exists") - - if self.status: - raise DeviceFormatError("device exists and is active") - - DeviceFormat.create(self, *args, **kwargs) - - # We're relying on someone having called resetPartedDisk -- we - # could ensure a fresh disklabel by setting self._partedDisk to - # None right before calling self.commit(), but that might hide - # other problems. - self.commit() - self.exists = True - - def destroy(self, *args, **kwargs): - """ Wipe the disklabel from the device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise DeviceFormatError("format does not exist") - - if not os.access(self.device, os.W_OK): - raise DeviceFormatError("device path does not exist") - - self.partedDevice.clobber() - self.exists = False - - def commit(self): - """ Commit the current partition table to disk and notify the OS. """ - log_method_call(self, device=self.device, - numparts=len(self.partitions)) - try: - self.partedDisk.commit() - except parted.DiskException as msg: - raise DiskLabelCommitError(msg) - else: - udev_settle() - - def commitToDisk(self): - """ Commit the current partition table to disk. """ - log_method_call(self, device=self.device, - numparts=len(self.partitions)) - try: - self.partedDisk.commitToDevice() - except parted.DiskException as msg: - raise DiskLabelCommitError(msg) - - def addPartition(self, *args, **kwargs): - partition = kwargs.get("partition", None) - if not partition: - partition = args[0] - geometry = partition.geometry - constraint = kwargs.get("constraint", None) - if not constraint and len(args) > 1: - constraint = args[1] - elif not constraint: - constraint = parted.Constraint(exactGeom=geometry) - - new_partition = parted.Partition(disk=self.partedDisk, - type=partition.type, - geometry=geometry) - self.partedDisk.addPartition(partition=new_partition, - constraint=constraint) - - def removePartition(self, partition): - self.partedDisk.removePartition(partition) - - @property - def extendedPartition(self): - try: - extended = self.partedDisk.getExtendedPartition() - except Exception: - extended = None - return extended - - @property - def logicalPartitions(self): - try: - logicals = self.partedDisk.getLogicalPartitions() - except Exception: - logicals = [] - return logicals - - @property - def firstPartition(self): - try: - part = self.partedDisk.getFirstPartition() - except Exception: - part = None - return part - - @property - def partitions(self): - try: - parts = self.partedDisk.partitions - except Exception: - parts = [] - if flags.testing: - sys_block_root = "/sys/class/block/" - - # FIXME: /dev/mapper/foo won't work without massaging - disk_name = self.device.split("/")[-1] - - disk_root = sys_block_root + disk_name - parts = [n for n in os.listdir(disk_root) if n.startswith(disk_name)] - return parts - - @property - def alignment(self): - """ Alignment requirements for this device. """ - if not self._alignment: - try: - disklabel_alignment = self.partedDisk.partitionAlignment - except _ped.CreateException: - disklabel_alignment = parted.Alignment(offset=0, grainSize=1) - - try: - optimum_device_alignment = self.partedDevice.optimumAlignment - except _ped.CreateException: - optimum_device_alignment = None - - try: - minimum_device_alignment = self.partedDevice.minimumAlignment - except _ped.CreateException: - minimum_device_alignment = None - - try: - a = optimum_device_alignment.intersect(disklabel_alignment) - except (ArithmeticError, AttributeError): - try: - a = minimum_device_alignment.intersect(disklabel_alignment) - except (ArithmeticError, AttributeError): - a = disklabel_alignment - - self._alignment = a - - return self._alignment - - @property - def endAlignment(self): - if not self._endAlignment: - self._endAlignment = parted.Alignment( - offset = self.alignment.offset - 1, - grainSize = self.alignment.grainSize) - - return self._endAlignment - - @property - def free(self): - def read_int_from_sys(path): - return int(open(path).readline().strip()) - - try: - free = sum([f.getSize() - for f in self.partedDisk.getFreeSpacePartitions()]) - except Exception: - sys_block_root = "/sys/class/block/" - - # FIXME: /dev/mapper/foo won't work without massaging - disk_name = self.device.split("/")[-1] - - disk_root = sys_block_root + disk_name - disk_length = read_int_from_sys("%s/size" % disk_root) - sector_size = read_int_from_sys("%s/queue/logical_block_size" % disk_root) - partition_names = [n for n in os.listdir(disk_root) if n.startswith(disk_name)] - used_sectors = 0 - for partition_name in partition_names: - partition_root = sys_block_root + partition_name - partition_length = read_int_from_sys("%s/size" % partition_root) - used_sectors += partition_length - - free = ((disk_length - used_sectors) * sector_size) / (1024.0 * 1024.0) - - return free - - @property - def magicPartitionNumber(self): - """ Number of disklabel-type-specific special partition. """ - if self.labelType == "mac": - return 1 - elif self.labelType == "sun": - return 3 - else: - return 0 - -register_device_format(DiskLabel) - diff --git a/pyanaconda/storage/formats/dmraid.py b/pyanaconda/storage/formats/dmraid.py deleted file mode 100644 index f37b2d33f..000000000 --- a/pyanaconda/storage/formats/dmraid.py +++ /dev/null @@ -1,114 +0,0 @@ -# dmraid.py -# dmraid device formats -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -from ..storage_log import log_method_call -from ..flags import flags -from ..errors import * -from . import DeviceFormat, register_device_format - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - - -class DMRaidMember(DeviceFormat): - """ A dmraid member disk. """ - _type = "dmraidmember" - _name = "dm-raid member device" - # XXX This looks like trouble. - # - # Maybe a better approach is a RaidMember format with subclass - # for MDRaidMember, letting all *_raid_member types fall through - # to the generic RaidMember format, which is basically read-only. - # - # One problem that presents is the possibility of someone passing - # a dmraid member to the MDRaidArrayDevice constructor. - _udevTypes = ["adaptec_raid_member", "ddf_raid_member", - "hpt37x_raid_member", "hpt45x_raid_member", - "isw_raid_member", - "jmicron_raid_member", "lsi_mega_raid_member", - "nvidia_raid_member", "promise_fasttrack_raid_member", - "silicon_medley_raid_member", "via_raid_member"] - _formattable = False # can be formatted - _supported = True # is supported - _linuxNative = False # for clearpart - _packages = ["dmraid"] # required packages - _resizable = False # can be resized - _maxSize = 0 # maximum size in MB - _minSize = 0 # minimum size in MB - _hidden = True # hide devices with this formatting? - - def __init__(self, *args, **kwargs): - """ Create a DeviceFormat instance. - - Keyword Arguments: - - device -- path to the underlying device - uuid -- this format's UUID - exists -- indicates whether this is an existing format - - On initialization this format is like DeviceFormat - - """ - log_method_call(self, *args, **kwargs) - DeviceFormat.__init__(self, *args, **kwargs) - - # Initialize the attribute that will hold the block object. - self._raidmem = None - - def __repr__(self): - s = DeviceFormat.__repr__(self) - s += (" raidmem = %(raidmem)r" % {"raidmem": self.raidmem}) - return s - - def _getRaidmem(self): - return self._raidmem - - def _setRaidmem(self, raidmem): - self._raidmem = raidmem - - raidmem = property(lambda d: d._getRaidmem(), - lambda d,r: d._setRaidmem(r)) - - def create(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - raise DMRaidMemberError("creation of dmraid members is non-sense") - - def destroy(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - raise DMRaidMemberError("destruction of dmraid members is non-sense") - - -if not flags.noiswmd: - DMRaidMember._udevTypes.remove("isw_raid_member") - -# The anaconda cmdline has not been parsed yet when we're first imported, -# so we can not use flags.dmraid here -if not flags.dmraid: - DMRaidMember._udevTypes = [] - -register_device_format(DMRaidMember) - diff --git a/pyanaconda/storage/formats/fs.py b/pyanaconda/storage/formats/fs.py deleted file mode 100644 index b472e8727..000000000 --- a/pyanaconda/storage/formats/fs.py +++ /dev/null @@ -1,1433 +0,0 @@ -# filesystems.py -# Filesystem classes for anaconda's storage configuration module. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# David Cantrell <dcantrell@redhat.com> -# - -""" Filesystem classes for use by anaconda. - - TODO: - - bug 472127: allow creation of tmpfs filesystems (/tmp, /var/tmp, &c) -""" -import math -import os -import sys -import tempfile -import selinux - -from ..errors import * -from . import DeviceFormat, register_device_format -from .. import util -from .. import platform -from ..flags import flags -from parted import fileSystemType -from ..storage_log import log_method_call - -import logging -log = logging.getLogger("storage") - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -try: - lost_and_found_context = selinux.matchpathcon("/lost+found", 0)[1] -except OSError: - lost_and_found_context = None - -# these are for converting to/from SI for ntfsresize -mb = 1000 * 1000.0 -mib = 1024 * 1024.0 - -fs_configs = {} - -def get_kernel_filesystems(): - fs_list = [] - for line in open("/proc/filesystems").readlines(): - fs_list.append(line.split()[-1]) - return fs_list - -global kernel_filesystems -kernel_filesystems = get_kernel_filesystems() - -def fsConfigFromFile(config_file): - """ Generate a set of attribute name/value pairs with which a - filesystem type can be defined. - - The following config file would define a filesystem identical to - the static Ext3FS class definition: - - type = ext3 - mkfs = "mke2fs" - resizefs = "resize2fs" - labelfs = "e2label" - fsck = "e2fsck" - packages = ["e2fsprogs"] - formattable = True - supported = True - resizable = True - linuxNative = True - maxSize = 8 * 1024 * 1024 - minSize = 0 - defaultFormatOptions = "-t ext3" - defaultMountOptions = "defaults" - - """ - # XXX NOTUSED - lines = open(config_file).readlines() - fs_attrs = {} - for line in lines: - (key, value) = [t.strip() for t in line.split("=")] - if not hasattr(FS, "_" + key): - print "invalid key: %s" % key - continue - - fs_attrs[key] = value - - if not fs_attrs.has_key("type"): - raise ValueError, _("filesystem configuration missing a type") - - # XXX what's the policy about multiple configs for a given type? - fs_configs[fs_attrs['type']] = fs_attrs - -class FS(DeviceFormat): - """ Filesystem class. """ - _type = "Abstract Filesystem Class" # fs type name - _mountType = None # like _type but for passing to mount - _name = None - _mkfs = "" # mkfs utility - _modules = [] # kernel modules required for support - _resizefs = "" # resize utility - _labelfs = "" # labeling utility - _fsck = "" # fs check utility - _fsckErrors = {} # fs check command error codes & msgs - _infofs = "" # fs info utility - _defaultFormatOptions = [] # default options passed to mkfs - _defaultMountOptions = ["defaults"] # default options passed to mount - _defaultLabelOptions = [] - _defaultCheckOptions = [] - _defaultInfoOptions = [] - _existingSizeFields = [] - _fsProfileSpecifier = None # mkfs option specifying fsprofile - - def __init__(self, *args, **kwargs): - """ Create a FS instance. - - Keyword Args: - - device -- path to the device containing the filesystem - mountpoint -- the filesystem's mountpoint - label -- the filesystem label - uuid -- the filesystem UUID - mountopts -- mount options for the filesystem - size -- the filesystem's size in MiB - exists -- indicates whether this is an existing filesystem - - """ - if self.__class__ is FS: - raise TypeError("FS is an abstract class.") - - DeviceFormat.__init__(self, *args, **kwargs) - self.mountpoint = kwargs.get("mountpoint") - self.mountopts = kwargs.get("mountopts") - self.label = kwargs.get("label") - self.fsprofile = kwargs.get("fsprofile") - - # filesystem size does not necessarily equal device size - self._size = kwargs.get("size", 0) - self._minInstanceSize = None # min size of this FS instance - self._mountpoint = None # the current mountpoint when mounted - if self.exists: - self._size = self._getExistingSize() - foo = self.minSize # force calculation of minimum size - - self._targetSize = self._size - - if self.supported: - self.loadModule() - - def __repr__(self): - s = DeviceFormat.__repr__(self) - s += (" mountpoint = %(mountpoint)s mountopts = %(mountopts)s\n" - " label = %(label)s size = %(size)s" - " targetSize = %(targetSize)s\n" % - {"mountpoint": self.mountpoint, "mountopts": self.mountopts, - "label": self.label, "size": self._size, - "targetSize": self.targetSize}) - return s - - @property - def desc(self): - s = "%s filesystem" % self.type - if self.mountpoint: - s += " mounted at %s" % self.mountpoint - return s - - @property - def dict(self): - d = super(FS, self).dict - d.update({"mountpoint": self.mountpoint, "size": self._size, - "label": self.label, "targetSize": self.targetSize, - "mountable": self.mountable}) - return d - - def _setTargetSize(self, newsize): - """ Set a target size for this filesystem. """ - if not self.exists: - raise FSError("filesystem has not been created") - - if newsize is None: - # unset any outstanding resize request - self._targetSize = self._size - return - - if not self.minSize <= newsize < self.maxSize: - raise ValueError("invalid target size request") - - self._targetSize = newsize - - def _getTargetSize(self): - """ Get this filesystem's target size. """ - return self._targetSize - - targetSize = property(_getTargetSize, _setTargetSize, - doc="Target size for this filesystem") - - def _getSize(self): - """ Get this filesystem's size. """ - size = self._size - if self.resizable and self.targetSize != size: - size = self.targetSize - return size - - size = property(_getSize, doc="This filesystem's size, accounting " - "for pending changes") - - def _getExistingSize(self): - """ Determine the size of this filesystem. Filesystem must - exist. Each filesystem varies, but the general procedure - is to run the filesystem dump or info utility and read - the block size and number of blocks for the filesystem - and compute megabytes from that. - - The loop that reads the output from the infofsProg is meant - to be simple, but take in to account variations in output. - The general procedure: - 1) Capture output from infofsProg. - 2) Iterate over each line of the output: - a) Trim leading and trailing whitespace. - b) Break line into fields split on ' ' - c) If line begins with any of the strings in - _existingSizeFields, start at the end of - fields and take the first one that converts - to a long. Store this in the values list. - d) Repeat until the values list length equals - the _existingSizeFields length. - 3) If the length of the values list equals the length - of _existingSizeFields, compute the size of this - filesystem by multiplying all of the values together - to get bytes, then convert to megabytes. Return - this value. - 4) If we were unable to capture all fields, return 0. - - The caller should catch exceptions from this method. Any - exception raised indicates a need to change the fields we - are looking for, the command to run and arguments, or - something else. If you catch an exception from this method, - assume the filesystem cannot be resized. - """ - size = self._size - - if self.infofsProg and self.exists and not size and \ - util.find_program_in_path(self.infofsProg): - try: - values = [] - argv = self._defaultInfoOptions + [ self.device ] - - buf = util.capture_output([self.infofsProg] + argv) - - for line in buf.splitlines(): - found = False - - line = line.strip() - tmp = line.split(' ') - tmp.reverse() - - for field in self._existingSizeFields: - if line.startswith(field): - for subfield in tmp: - try: - values.append(long(subfield)) - found = True - break - except ValueError: - continue - - if found: - break - - if len(values) == len(self._existingSizeFields): - break - - if len(values) != len(self._existingSizeFields): - return 0 - - size = 1 - for value in values: - size *= value - - # report current size as megabytes - size = math.floor(size / 1024.0 / 1024.0) - except Exception as e: - log.error("failed to obtain size of filesystem on %s: %s" - % (self.device, e)) - - return size - - @property - def currentSize(self): - """ The filesystem's current actual size. """ - size = 0 - if self.exists: - size = self._size - return float(size) - - @property - def free(self): - free = 0 - if self.exists: - if self.currentSize and self.minSize and \ - self.currentSize != self.minSize: - free = int(max(0, self.currentSize - self.minSize)) # truncate - - return free - - def _getFormatOptions(self, options=None): - argv = [] - if options and isinstance(options, list): - argv.extend(options) - argv.extend(self.defaultFormatOptions) - if self._fsProfileSpecifier and self.fsprofile: - argv.extend([self._fsProfileSpecifier, self.fsprofile]) - argv.append(self.device) - return argv - - def doFormat(self, *args, **kwargs): - """ Create the filesystem. - - Arguments: - - None - - Keyword Arguments: - - options -- list of options to pass to mkfs - - """ - log_method_call(self, type=self.mountType, device=self.device, - mountpoint=self.mountpoint) - - options = kwargs.get("options") - - if self.exists: - raise FormatCreateError("filesystem already exists", self.device) - - if not self.formattable: - return - - if not self.mkfsProg: - return - - if self.exists: - return - - if not os.path.exists(self.device): - raise FormatCreateError("device does not exist", self.device) - - argv = self._getFormatOptions(options=options) - - try: - ret = util.run_program([self.mkfsProg] + argv) - except OSError as e: - raise FormatCreateError(e, self.device) - - if ret: - raise FormatCreateError("format failed: %s" % ret.rc, self.device) - - self.exists = True - self.notifyKernel() - - if self.label: - self.writeLabel(self.label) - - @property - def resizeArgs(self): - argv = [self.device, "%d" % (self.targetSize,)] - return argv - - def doResize(self, *args, **kwargs): - """ Resize this filesystem to new size @newsize. - - Arguments: - - None - """ - - if not self.exists: - raise FSResizeError("filesystem does not exist", self.device) - - if not self.resizable: - raise FSResizeError("filesystem not resizable", self.device) - - if self.targetSize == self.currentSize: - return - - if not self.resizefsProg: - return - - if not os.path.exists(self.device): - raise FSResizeError("device does not exist", self.device) - - self.doCheck() - - # The first minimum size can be incorrect if the fs was not - # properly unmounted. After doCheck the minimum size will be correct - # so run the check one last time and bump up the size if it was too - # small. - self._minInstanceSize = None - if self.targetSize < self.minSize: - self.targetSize = self.minSize - log.info("Minimum size changed, setting targetSize on %s to %s" \ - % (self.device, self.targetSize)) - try: - ret = util.run_program([self.resizefsProg] + self.resizeArgs) - except OSError as e: - raise FSResizeError(e, self.device) - - if ret: - raise FSResizeError("resize failed: %s" % ret, self.device) - - self.doCheck() - - # XXX must be a smarter way to do this - self._size = self.targetSize - self.notifyKernel() - - def _getCheckArgs(self): - argv = [] - argv.extend(self.defaultCheckOptions) - argv.append(self.device) - return argv - - def _fsckFailed(self, rc): - return False - - def _fsckErrorMessage(self, rc): - return _("Unknown return code: %d.") % (rc,) - - def doCheck(self): - if not self.exists: - raise FSError("filesystem has not been created") - - if not self.fsckProg: - return - - if not os.path.exists(self.device): - raise FSError("device does not exist") - - try: - ret = util.run_program([self.fsckProg] + self._getCheckArgs()) - except OSError as e: - raise FSError("filesystem check failed: %s" % e) - - if self._fsckFailed(ret): - hdr = _("%(type)s filesystem check failure on %(device)s: ") % \ - {"type": self.type, "device": self.device} - - msg = self._fsckErrorMessage(ret) - raise FSError(hdr + msg) - - def loadModule(self): - """Load whatever kernel module is required to support this filesystem.""" - global kernel_filesystems - - if not self._modules or self.mountType in kernel_filesystems: - return - - for module in self._modules: - try: - rc = util.run_program(["modprobe", module]) - except OSError as e: - log.error("Could not load kernel module %s: %s" % (module, e)) - self._supported = False - return - - if rc: - log.error("Could not load kernel module %s" % module) - self._supported = False - return - - # If we successfully loaded a kernel module, for this filesystem, we - # also need to update the list of supported filesystems. - kernel_filesystems = get_kernel_filesystems() - - def testMount(self, options=None): - """ Try to mount the fs and return True if successful. """ - ret = False - - if self.status: - raise RuntimeError("filesystem is already mounted") - - # create a temp dir - prefix = "%s.%s" % (os.path.basename(self.device), self.type) - mountpoint = tempfile.mkdtemp(prefix=prefix) - - # try the mount - try: - self.mount(mountpoint=mountpoint) - except Exception as e: - log.info("test mount failed: %s" % e) - else: - self.unmount() - ret = True - finally: - os.rmdir(mountpoint) - - return ret - - def mount(self, *args, **kwargs): - """ Mount this filesystem. - - Arguments: - - None - - Keyword Arguments: - - options -- mount options (overrides all other option strings) - chroot -- prefix to apply to mountpoint - mountpoint -- mountpoint (overrides self.mountpoint) - """ - options = kwargs.get("options", "") - chroot = kwargs.get("chroot", "/") - mountpoint = kwargs.get("mountpoint") - - if not self.exists: - raise FSError("filesystem has not been created") - - if not mountpoint: - mountpoint = self.mountpoint - - if not mountpoint: - raise FSError("no mountpoint given") - - if self.status: - return - - if not isinstance(self, NoDevFS) and not os.path.exists(self.device): - raise FSError("device %s does not exist" % self.device) - - # XXX os.path.join is FUBAR: - # - # os.path.join("/mnt/foo", "/") -> "/" - # - #mountpoint = os.path.join(chroot, mountpoint) - chrootedMountpoint = os.path.normpath("%s/%s" % (chroot, mountpoint)) - util.makedirs(chrootedMountpoint) - if flags.selinux: - ret = util.reset_file_context(mountpoint, chroot) - log.info("set SELinux context for mountpoint %s to %s" \ - % (mountpoint, ret)) - - # passed in options override default options - if not options or not isinstance(options, str): - options = self.options - - if isinstance(self, BindFS): - options = "bind," + options - - try: - rc = util.mount(self.device, chrootedMountpoint, - fstype=self.mountType, - options=options) - except Exception as e: - raise FSError("mount failed: %s" % e) - - if rc: - raise FSError("mount failed: %s" % rc) - - if flags.selinux and "ro" not in options.split(","): - ret = util.reset_file_context(mountpoint, chroot) - log.info("set SELinux context for newly mounted filesystem " - "root at %s to %s" %(mountpoint, ret)) - util.set_file_context("%s/lost+found" % mountpoint, - lost_and_found_context, chroot) - - self._mountpoint = chrootedMountpoint - - def unmount(self): - """ Unmount this filesystem. """ - if not self.exists: - raise FSError("filesystem has not been created") - - if not self._mountpoint: - # not mounted - return - - if not os.path.exists(self._mountpoint): - raise FSError("mountpoint does not exist") - - rc = util.umount(self._mountpoint) - if rc: - raise FSError("umount failed") - - self._mountpoint = None - - def _getLabelArgs(self, label): - argv = [] - argv.extend(self.defaultLabelOptions) - argv.extend([self.device, label]) - return argv - - def writeLabel(self, label): - """ Create a label for this filesystem. """ - if not self.exists: - raise FSError("filesystem has not been created") - - if not self.labelfsProg: - return - - if not os.path.exists(self.device): - raise FSError("device does not exist") - - argv = self._getLabelArgs(label) - rc = util.run_program([self.labelfsProg] + argv) - if rc: - raise FSError("label failed") - - self.label = label - self.notifyKernel() - - def _getRandomUUID(self): - uuid = util.capture_output(["uuidgen"]).strip() - return uuid - - def writeRandomUUID(self): - raise NotImplementedError("FS does not implement writeRandomUUID") - - @property - def needsFSCheck(self): - return False - - @property - def mkfsProg(self): - """ Program used to create filesystems of this type. """ - return self._mkfs - - @property - def fsckProg(self): - """ Program used to check filesystems of this type. """ - return self._fsck - - @property - def resizefsProg(self): - """ Program used to resize filesystems of this type. """ - return self._resizefs - - @property - def labelfsProg(self): - """ Program used to manage labels for this filesystem type. """ - return self._labelfs - - @property - def infofsProg(self): - """ Program used to get information for this filesystem type. """ - return self._infofs - - @property - def utilsAvailable(self): - # we aren't checking for fsck because we shouldn't need it - for prog in [self.mkfsProg, self.resizefsProg, self.labelfsProg, - self.infofsProg]: - if not prog: - continue - - if not util.find_program_in_path(prog): - return False - - return True - - @property - def supported(self): - log_method_call(self, supported=self._supported) - return self._supported and self.utilsAvailable - - @property - def mountable(self): - canmount = (self.mountType in kernel_filesystems) or \ - (os.access("/sbin/mount.%s" % (self.mountType,), os.X_OK)) - modpath = os.path.realpath(os.path.join("/lib/modules", os.uname()[2])) - modname = "%s.ko" % self.mountType - - if not canmount and os.path.isdir(modpath): - for root, dirs, files in os.walk(modpath): - have = filter(lambda x: x.startswith(modname), files) - if len(have) == 1 and have[0].startswith(modname): - return True - - return canmount - - @property - def resizable(self): - """ Can formats of this filesystem type be resized? """ - return super(FS, self).resizable and self.utilsAvailable - - @property - def defaultFormatOptions(self): - """ Default options passed to mkfs for this filesystem type. """ - # return a copy to prevent modification - return self._defaultFormatOptions[:] - - @property - def defaultMountOptions(self): - """ Default options passed to mount for this filesystem type. """ - # return a copy to prevent modification - return self._defaultMountOptions[:] - - @property - def defaultLabelOptions(self): - """ Default options passed to labeler for this filesystem type. """ - # return a copy to prevent modification - return self._defaultLabelOptions[:] - - @property - def defaultCheckOptions(self): - """ Default options passed to checker for this filesystem type. """ - # return a copy to prevent modification - return self._defaultCheckOptions[:] - - def _getOptions(self): - options = ",".join(self.defaultMountOptions) - if self.mountopts: - # XXX should we clobber or append? - options = self.mountopts - return options - - def _setOptions(self, options): - self.mountopts = options - - options = property(_getOptions, _setOptions) - - @property - def mountType(self): - if not self._mountType: - self._mountType = self._type - - return self._mountType - - # These methods just wrap filesystem-specific methods in more - # generically named methods so filesystems and formatted devices - # like swap and LVM physical volumes can have a common API. - def create(self, *args, **kwargs): - if self.exists: - raise FSError("filesystem already exists") - - DeviceFormat.create(self, *args, **kwargs) - - return self.doFormat(*args, **kwargs) - - def setup(self, *args, **kwargs): - """ Mount the filesystem. - - The filesystem will be mounted at the directory indicated by - self.mountpoint. - """ - return self.mount(**kwargs) - - def teardown(self, *args, **kwargs): - return self.unmount(*args, **kwargs) - - @property - def status(self): - # FIXME check /proc/mounts or similar - if not self.exists: - return False - return self._mountpoint is not None - - def sync(self, root="/"): - pass - -class Ext2FS(FS): - """ ext2 filesystem. """ - _type = "ext2" - _mkfs = "mke2fs" - _modules = ["ext2"] - _resizefs = "resize2fs" - _labelfs = "e2label" - _fsck = "e2fsck" - _fsckErrors = {4: _("File system errors left uncorrected."), - 8: _("Operational error."), - 16: _("Usage or syntax error."), - 32: _("e2fsck cancelled by user request."), - 128: _("Shared library error.")} - _packages = ["e2fsprogs"] - _formattable = True - _supported = True - _resizable = True - _linuxNative = True - _maxSize = 8 * 1024 * 1024 - _minSize = 0 - _defaultFormatOptions = [] - _defaultMountOptions = ["defaults"] - _defaultCheckOptions = ["-f", "-p", "-C", "0"] - _dump = True - _check = True - _infofs = "dumpe2fs" - _defaultInfoOptions = ["-h"] - _existingSizeFields = ["Block count:", "Block size:"] - _fsProfileSpecifier = "-T" - partedSystem = fileSystemType["ext2"] - - def __init__(self, *args, **kwargs): - self.dirty = False - self.errors = False - super(Ext2FS, self).__init__(*args, **kwargs) - - def _fsckFailed(self, rc): - for errorCode in self._fsckErrors.keys(): - if rc & errorCode: - return True - return False - - def _fsckErrorMessage(self, rc): - msg = '' - - for errorCode in self._fsckErrors.keys(): - if rc & errorCode: - msg += "\n" + self._fsckErrors[errorCode] - - return msg.strip() - - def writeRandomUUID(self): - if not self.exists: - raise FSError("filesystem does not exist") - - err = None - try: - rc = util.run_program(["tune2fs", "-U", "random", self.device]) - except OSError as e: - err = str(e) - else: - if rc: - err = rc - - if err: - raise FSError("failed to set UUID for %s: %s" % (self.device, err)) - - @property - def minSize(self): - """ Minimum size for this filesystem in MB. """ - if self._minInstanceSize is None: - # try once in the beginning to get the minimum size for an - # existing filesystem. - size = self._minSize - blockSize = None - - if self.exists and os.path.exists(self.device): - # get block size - buf = util.capture_output([self.infofsProg, "-h", self.device]) - for line in buf.splitlines(): - if line.startswith("Block size:"): - blockSize = int(line.split(" ")[-1]) - - if line.startswith("Filesystem state:"): - self.dirty = "not clean" in line - self.errors = "with errors" in line - - if blockSize is None: - raise FSError("failed to get block size for %s filesystem " - "on %s" % (self.mountType, self.device)) - - # get minimum size according to resize2fs - buf = util.capture_output([self.resizefsProg, - "-P", self.device]) - for line in buf.splitlines(): - if "minimum size of the filesystem:" not in line: - continue - - # line will look like: - # Estimated minimum size of the filesystem: 1148649 - # - # NOTE: The minimum size reported is in blocks. Convert - # to bytes, then megabytes, and finally round up. - (text, sep, minSize) = line.partition(": ") - size = long(minSize) * blockSize - size = math.ceil(size / 1024.0 / 1024.0) - break - - if size is None: - log.warning("failed to get minimum size for %s filesystem " - "on %s" % (self.mountType, self.device)) - else: - orig_size = size - size = min(size * 1.1, size + 500, self.currentSize) - if orig_size < size: - log.debug("padding min size from %d up to %d" % (orig_size, size)) - else: - log.debug("using current size %d as min size" % size) - - self._minInstanceSize = size - - return self._minInstanceSize - - @property - def needsFSCheck(self): - return self.dirty or self.errors - - @property - def resizeArgs(self): - argv = ["-p", self.device, "%dM" % (self.targetSize,)] - return argv - -register_device_format(Ext2FS) - - -class Ext3FS(Ext2FS): - """ ext3 filesystem. """ - _type = "ext3" - _defaultFormatOptions = ["-t", "ext3"] - _modules = ["ext3"] - partedSystem = fileSystemType["ext3"] - - # It is possible for a user to specify an fsprofile that defines a blocksize - # smaller than the default of 4096 bytes and therefore to make liars of us - # with regard to this maximum filesystem size, but if they're doing such - # things they should know the implications of their chosen block size. - _maxSize = 16 * 1024 * 1024 - - @property - def needsFSCheck(self): - return self.errors - -register_device_format(Ext3FS) - - -class Ext4FS(Ext3FS): - """ ext4 filesystem. """ - _type = "ext4" - _defaultFormatOptions = ["-t", "ext4"] - _modules = ["ext4"] - partedSystem = fileSystemType["ext4"] - -register_device_format(Ext4FS) - - -class FATFS(FS): - """ FAT filesystem. """ - _type = "vfat" - _mkfs = "mkdosfs" - _modules = ["vfat"] - _labelfs = "dosfslabel" - _fsck = "dosfsck" - _fsckErrors = {1: _("Recoverable errors have been detected or dosfsck has " - "discovered an internal inconsistency."), - 2: _("Usage error.")} - _supported = True - _formattable = True - _maxSize = 1024 * 1024 - _packages = [ "dosfstools" ] - _defaultMountOptions = ["umask=0077", "shortname=winnt"] - # FIXME this should be fat32 in some cases - partedSystem = fileSystemType["fat16"] - - def _fsckFailed(self, rc): - if rc >= 1: - return True - return False - - def _fsckErrorMessage(self, rc): - return self._fsckErrors[rc] - -register_device_format(FATFS) - - -class EFIFS(FATFS): - _type = "efi" - _mountType = "vfat" - _modules = ["vfat"] - _name = "EFI System Partition" - _minSize = 50 - - @property - def supported(self): - return (isinstance(platform.platform, platform.EFI) and - self.utilsAvailable) - -register_device_format(EFIFS) - - -class BTRFS(FS): - """ btrfs filesystem """ - _type = "btrfs" - _mkfs = "mkfs.btrfs" - _modules = ["btrfs"] - _resizefs = "btrfsctl" - _formattable = True - _linuxNative = True - _maxLabelChars = 256 - _supported = True - _dump = True - _check = True - _packages = ["btrfs-progs"] - _minSize = 256 - _maxSize = 16 * 1024 * 1024 - # FIXME parted needs to be taught about btrfs so that we can set the - # partition table type correctly for btrfs partitions - # partedSystem = fileSystemType["btrfs"] - - def __init__(self, *args, **kwargs): - super(BTRFS, self).__init__(*args, **kwargs) - self.volUUID = kwargs.pop("volUUID", None) - - def create(self, *args, **kwargs): - # filesystem creation is done in storage.devicelibs.btrfs.create_volume - pass - - def destroy(self, *args, **kwargs): - # filesystem creation is done in storage.devicelibs.btrfs.delete_volume - pass - - def setup(self, *args, **kwargs): - log_method_call(self, type=self.mountType, device=self.device, - mountpoint=self.mountpoint) - if not self.mountpoint and "mountpoint" not in kwargs: - # Since btrfs vols have subvols the format setup is automatic. - # Don't try to mount it if there's no mountpoint. - return - - return self.mount(*args, **kwargs) - - def _getFormatOptions(self, options=None): - argv = [] - if options and isinstance(options, list): - argv.extend(options) - argv.extend(self.defaultFormatOptions) - if self.label: - argv.extend(["-L", self.label]) - argv.append(self.device) - return argv - - @property - def resizeArgs(self): - argv = ["-r", "%dm" % (self.targetSize,), self.device] - return argv - -register_device_format(BTRFS) - - -class GFS2(FS): - """ gfs2 filesystem. """ - _type = "gfs2" - _mkfs = "mkfs.gfs2" - _modules = ["dlm", "gfs2"] - _formattable = True - _defaultFormatOptions = ["-j", "1", "-p", "lock_nolock", "-O"] - _linuxNative = True - _supported = False - _dump = True - _check = True - _packages = ["gfs2-utils"] - # FIXME parted needs to be thaught about btrfs so that we can set the - # partition table type correctly for btrfs partitions - # partedSystem = fileSystemType["gfs2"] - - @property - def supported(self): - """ Is this filesystem a supported type? """ - supported = self._supported - if flags.gfs2: - supported = self.utilsAvailable - - return supported - -register_device_format(GFS2) - - -class JFS(FS): - """ JFS filesystem """ - _type = "jfs" - _mkfs = "mkfs.jfs" - _modules = ["jfs"] - _labelfs = "jfs_tune" - _defaultFormatOptions = ["-q"] - _defaultLabelOptions = ["-L"] - _maxLabelChars = 16 - _maxSize = 8 * 1024 * 1024 - _formattable = True - _linuxNative = True - _supported = False - _dump = True - _check = True - _infofs = "jfs_tune" - _defaultInfoOptions = ["-l"] - _existingSizeFields = ["Aggregate block size:", "Aggregate size:"] - partedSystem = fileSystemType["jfs"] - - @property - def supported(self): - """ Is this filesystem a supported type? """ - supported = self._supported - if flags.jfs: - supported = self.utilsAvailable - - return supported - -register_device_format(JFS) - - -class ReiserFS(FS): - """ reiserfs filesystem """ - _type = "reiserfs" - _mkfs = "mkreiserfs" - _resizefs = "resize_reiserfs" - _labelfs = "reiserfstune" - _modules = ["reiserfs"] - _defaultFormatOptions = ["-f", "-f"] - _defaultLabelOptions = ["-l"] - _maxLabelChars = 16 - _maxSize = 16 * 1024 * 1024 - _formattable = True - _linuxNative = True - _supported = False - _dump = True - _check = True - _packages = ["reiserfs-utils"] - _infofs = "debugreiserfs" - _defaultInfoOptions = [] - _existingSizeFields = ["Count of blocks on the device:", "Blocksize:"] - partedSystem = fileSystemType["reiserfs"] - - @property - def supported(self): - """ Is this filesystem a supported type? """ - supported = self._supported - if flags.reiserfs: - supported = self.utilsAvailable - - return supported - - @property - def resizeArgs(self): - argv = ["-s", "%dM" % (self.targetSize,), self.device] - return argv - -register_device_format(ReiserFS) - - -class XFS(FS): - """ XFS filesystem """ - _type = "xfs" - _mkfs = "mkfs.xfs" - _modules = ["xfs"] - _labelfs = "xfs_admin" - _defaultFormatOptions = ["-f"] - _defaultLabelOptions = ["-L"] - _maxLabelChars = 16 - _maxSize = 16 * 1024 * 1024 - _formattable = True - _linuxNative = True - _supported = True - _dump = True - _check = True - _packages = ["xfsprogs"] - _infofs = "xfs_db" - _defaultInfoOptions = ["-c", "\"sb 0\"", "-c", "\"p dblocks\"", - "-c", "\"p blocksize\""] - _existingSizeFields = ["dblocks =", "blocksize ="] - partedSystem = fileSystemType["xfs"] - - def _getLabelArgs(self, label): - argv = [] - argv.extend(self.defaultLabelOptions) - argv.extend([label, self.device]) - return argv - - def sync(self, root='/'): - """ Ensure that data we've written is at least in the journal. - - This is a little odd because xfs_freeze will only be - available under the install root. - """ - if not self.status or not self._mountpoint.startswith(root): - return - - try: - util.run_program(["xfs_freeze", "-f", self.mountpoint], root=root) - except OSError as e: - log.error("failed to run xfs_freeze: %s" % e) - - try: - util.run_program(["xfs_freeze", "-u", self.mountpoint], root=root) - except OSError as e: - log.error("failed to run xfs_freeze: %s" % e) - -register_device_format(XFS) - - -class HFS(FS): - _type = "hfs" - _mkfs = "hformat" - _modules = ["hfs"] - _formattable = True - partedSystem = fileSystemType["hfs"] - -register_device_format(HFS) - - -class AppleBootstrapFS(HFS): - _type = "appleboot" - _mountType = "hfs" - _name = "Apple Bootstrap" - _minSize = 800.00 / 1024.00 - _maxSize = 1 - - @property - def supported(self): - return (isinstance(platform.platform, platform.NewWorldPPC) - and self.utilsAvailable) - -register_device_format(AppleBootstrapFS) - - -class HFSPlus(FS): - _type = "hfs+" - _modules = ["hfsplus"] - _udevTypes = ["hfsplus"] - _mkfs = "mkfs.hfsplus" - _fsck = "fsck.hfsplus" - _packages = ["hfsplus-tools"] - _formattable = True - _mountType = "hfsplus" - _minSize = 1 - _maxSize = 2 * 1024 * 1024 - _check = True - partedSystem = fileSystemType["hfs+"] - -register_device_format(HFSPlus) - - -class NTFS(FS): - """ ntfs filesystem. """ - _type = "ntfs" - _resizefs = "ntfsresize" - _fsck = "ntfsresize" - _resizable = True - _minSize = 1 - _maxSize = 16 * 1024 * 1024 - _defaultMountOptions = ["defaults", "ro"] - _defaultCheckOptions = ["-c"] - _packages = ["ntfsprogs"] - _infofs = "ntfsinfo" - _defaultInfoOptions = ["-m"] - _existingSizeFields = ["Cluster Size:", "Volume Size in Clusters:"] - partedSystem = fileSystemType["ntfs"] - - @property - def mountable(self): - return False - - def _fsckFailed(self, rc): - if rc != 0: - return True - return False - - @property - def minSize(self): - """ The minimum filesystem size in megabytes. """ - if self._minInstanceSize is None: - # we try one time to determine the minimum size. - size = self._minSize - if self.exists and os.path.exists(self.device) and \ - util.find_program_in_path(self.resizefsProg): - minSize = None - buf = util.run_program([self.resizefsProg, "-m", self.device]) - for l in buf.split("\n"): - if not l.startswith("Minsize"): - continue - try: - minSize = int(l.split(":")[1].strip()) # MB - minSize *= (mb / mib) # MiB - except (IndexError, ValueError) as e: - minSize = None - log.warning("Unable to parse output for minimum size on %s: %s" %(self.device, e)) - - if minSize is None: - log.warning("Unable to discover minimum size of filesystem " - "on %s" %(self.device,)) - else: - size = min(minSize * 1.1, minSize + 500, self.currentSize) - if minSize < size: - log.debug("padding min size from %d up to %d" % (minSize, size)) - else: - log.debug("using current size %d as min size" % size) - - self._minInstanceSize = size - - return self._minInstanceSize - - @property - def resizeArgs(self): - # You must supply at least two '-f' options to ntfsresize or - # the proceed question will be presented to you. - - # FIXME: This -1 is because our partition alignment calculations plus - # converting back and forth between MiB and MB means the filesystem is - # getting resized to be slightly larger than the partition holding it. - # This hack just makes the filesystem fit. - targetSize = (mib / mb) * (self.targetSize-1) # convert MiB to MB - argv = ["-ff", "-s", "%dM" % (targetSize,), self.device] - return argv - - -register_device_format(NTFS) - - -# if this isn't going to be mountable it might as well not be here -class NFS(FS): - """ NFS filesystem. """ - _type = "nfs" - _modules = ["nfs"] - - def _deviceCheck(self, devspec): - if devspec is not None and ":" not in devspec: - raise ValueError("device must be of the form <host>:<path>") - - @property - def mountable(self): - return False - - def _setDevice(self, devspec): - self._deviceCheck(devspec) - self._device = devspec - - def _getDevice(self): - return self._device - - device = property(lambda f: f._getDevice(), - lambda f,d: f._setDevice(d), - doc="Full path the device this format occupies") - -register_device_format(NFS) - - -class NFSv4(NFS): - """ NFSv4 filesystem. """ - _type = "nfs4" - _modules = ["nfs4"] - -register_device_format(NFSv4) - - -class Iso9660FS(FS): - """ ISO9660 filesystem. """ - _type = "iso9660" - _formattable = False - _supported = True - _resizable = False - _linuxNative = False - _dump = False - _check = False - _defaultMountOptions = ["ro"] - -register_device_format(Iso9660FS) - - -class NoDevFS(FS): - """ nodev filesystem base class """ - _type = "nodev" - - def __init__(self, *args, **kwargs): - FS.__init__(self, *args, **kwargs) - self.exists = True - self.device = self.type - - def _setDevice(self, devspec): - self._device = devspec - - def _getExistingSize(self): - pass - -register_device_format(NoDevFS) - - -class DevPtsFS(NoDevFS): - """ devpts filesystem. """ - _type = "devpts" - _defaultMountOptions = ["gid=5", "mode=620"] - -register_device_format(DevPtsFS) - - -# these don't really need to be here -class ProcFS(NoDevFS): - _type = "proc" - -register_device_format(ProcFS) - - -class SysFS(NoDevFS): - _type = "sysfs" - -register_device_format(SysFS) - - -class TmpFS(NoDevFS): - _type = "tmpfs" - -register_device_format(TmpFS) - - -class BindFS(FS): - _type = "bind" - - @property - def mountable(self): - return True - - def _getExistingSize(self): - pass - -register_device_format(BindFS) - - -class SELinuxFS(NoDevFS): - _type = "selinuxfs" - - @property - def mountable(self): - return flags.selinux and super(SELinuxFS, self).mountable - -register_device_format(SELinuxFS) - - -class USBFS(NoDevFS): - _type = "usbfs" - -register_device_format(USBFS) - diff --git a/pyanaconda/storage/formats/luks.py b/pyanaconda/storage/formats/luks.py deleted file mode 100644 index 4b37cb430..000000000 --- a/pyanaconda/storage/formats/luks.py +++ /dev/null @@ -1,342 +0,0 @@ -# luks.py -# Device format classes for anaconda's storage configuration module. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - - - -import os - -try: - import volume_key -except ImportError: - volume_key = None - -from ..storage_log import log_method_call -from ..errors import * -from ..devicelibs import crypto -from . import DeviceFormat, register_device_format - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - - -class LUKS(DeviceFormat): - """ A LUKS device. """ - _type = "luks" - _name = "LUKS" - _lockedName = _("Encrypted") - _udevTypes = ["crypto_LUKS"] - _formattable = True # can be formatted - _supported = False # is supported - _linuxNative = True # for clearpart - _packages = ["cryptsetup-luks"] # required packages - - def __init__(self, *args, **kwargs): - """ Create a LUKS instance. - - Keyword Arguments: - - device -- the path to the underlying device - name -- the name of the mapped device - uuid -- this device's UUID - passphrase -- device passphrase (string) - key_file -- path to a file containing a key (string) - cipher -- cipher mode string - key_size -- key size in bits - exists -- indicates whether this is an existing format - escrow_cert -- certificate to use for key escrow - add_backup_passphrase -- generate a backup passphrase? - """ - log_method_call(self, *args, **kwargs) - DeviceFormat.__init__(self, *args, **kwargs) - self.cipher = kwargs.get("cipher") - self.key_size = kwargs.get("key_size") - self.mapName = kwargs.get("name") - - if not self.exists and not self.cipher: - self.cipher = "aes-xts-plain64" - if not self.key_size: - # default to the max (512 bits) for aes-xts - self.key_size = 512 - - # FIXME: these should both be lists, but managing them will be a pain - self.__passphrase = kwargs.get("passphrase") - self._key_file = kwargs.get("key_file") - self.escrow_cert = kwargs.get("escrow_cert") - self.add_backup_passphrase = kwargs.get("add_backup_passphrase", False) - - if not self.mapName and self.exists and self.uuid: - self.mapName = "luks-%s" % self.uuid - elif not self.mapName and self.device: - self.mapName = "luks-%s" % os.path.basename(self.device) - - def __repr__(self): - s = DeviceFormat.__repr__(self) - if self.__passphrase: - passphrase = "(set)" - else: - passphrase = "(not set)" - s += (" cipher = %(cipher)s keySize = %(keySize)s" - " mapName = %(mapName)s\n" - " keyFile = %(keyFile)s passphrase = %(passphrase)s\n" - " escrowCert = %(escrowCert)s addBackup = %(backup)s" % - {"cipher": self.cipher, "keySize": self.key_size, - "mapName": self.mapName, "keyFile": self._key_file, - "passphrase": passphrase, "escrowCert": self.escrow_cert, - "backup": self.add_backup_passphrase}) - return s - - @property - def dict(self): - d = super(LUKS, self).dict - d.update({"cipher": self.cipher, "keySize": self.key_size, - "mapName": self.mapName, "hasKey": self.hasKey, - "escrowCert": self.escrow_cert, - "backup": self.add_backup_passphrase}) - return d - - @property - def name(self): - name = self._name - # for existing locked devices, show "Encrypted" instead of LUKS - if self.hasKey or not self.exists: - name = self._name - else: - name = "%s (%s)" % (self._lockedName, self._name) - return name - - def _setPassphrase(self, passphrase): - """ Set the passphrase used to access this device. """ - self.__passphrase = passphrase - - passphrase = property(fset=_setPassphrase) - - @property - def hasKey(self): - return ((self.__passphrase not in ["", None]) or - (self._key_file and os.access(self._key_file, os.R_OK))) - - @property - def configured(self): - """ To be ready we need a key or passphrase and a map name. """ - return self.hasKey and self.mapName - - @property - def status(self): - if not self.exists or not self.mapName: - return False - return os.path.exists("/dev/mapper/%s" % self.mapName) - - def probe(self): - """ Probe for any missing information about this format. - - cipher mode, key size - """ - raise NotImplementedError("probe method not defined for LUKS") - - def setup(self, *args, **kwargs): - """ Open, or set up, the format. """ - log_method_call(self, device=self.device, mapName=self.mapName, - type=self.type, status=self.status) - if not self.configured: - raise LUKSError("luks device not configured") - - if self.status: - return - - DeviceFormat.setup(self, *args, **kwargs) - crypto.luks_open(self.device, self.mapName, - passphrase=self.__passphrase, - key_file=self._key_file) - - def teardown(self, *args, **kwargs): - """ Close, or tear down, the format. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise LUKSError("format has not been created") - - if self.status: - log.debug("unmapping %s" % self.mapName) - crypto.luks_close(self.mapName) - - def create(self, *args, **kwargs): - """ Create the format. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.hasKey: - raise LUKSError("luks device has no key/passphrase") - - try: - DeviceFormat.create(self, *args, **kwargs) - crypto.luks_format(self.device, - passphrase=self.__passphrase, - key_file=self._key_file, - cipher=self.cipher, - key_size=self.key_size) - except Exception: - raise - else: - self.uuid = crypto.luks_uuid(self.device) - self.exists = True - self.mapName = "luks-%s" % self.uuid - self.notifyKernel() - - def destroy(self, *args, **kwargs): - """ Create the format. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - self.teardown() - DeviceFormat.destroy(self, *args, **kwargs) - - @property - def keyFile(self): - """ Path to key file to be used in /etc/crypttab """ - return self._key_file - - def addKeyFromFile(self, keyfile): - """ Add a new key from a file. - - Add the contents of the specified key file to an available key - slot in the LUKS header. - """ - log_method_call(self, device=self.device, - type=self.type, status=self.status, file=keyfile) - if not self.exists: - raise LUKSError("format has not been created") - - crypto.luks_add_key(self.device, - passphrase=self.__passphrase, - key_file=self._key_file, - new_key_file=keyfile) - - def addPassphrase(self, passphrase): - """ Add a new passphrase. - - Add the specified passphrase to an available key slot in the - LUKS header. - """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise LUKSError("format has not been created") - - crypto.luks_add_key(self.device, - passphrase=self.__passphrase, - key_file=self._key_file, - new_passphrase=passphrase) - - def removeKeyFromFile(self, keyfile): - """ Remove a key contained in a file. - - Remove key contained in the specified key file from the LUKS - header. - """ - log_method_call(self, device=self.device, - type=self.type, status=self.status, file=keyfile) - if not self.exists: - raise LUKSError("format has not been created") - - crypto.luks_remove_key(self.device, - passphrase=self.__passphrase, - key_file=self._key_file, - del_key_file=keyfile) - - - def removePassphrase(self, passphrase): - """ Remove the specified passphrase from the LUKS header. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise LUKSError("format has not been created") - - crypto.luks_remove_key(self.device, - passphrase=self.__passphrase, - key_file=self._key_file, - del_passphrase=passphrase) - - def _escrowVolumeIdent(self, vol): - """ Return an escrow packet filename prefix for a volume_key.Volume. """ - label = vol.label - if label is not None: - label = label.replace("/", "_") - uuid = vol.uuid - if uuid is not None: - uuid = uuid.replace("/", "_") - # uuid is never None on LUKS volumes - if label is not None and uuid is not None: - volume_ident = "%s-%s" % (label, uuid) - elif uuid is not None: - volume_ident = uuid - elif label is not None: - volume_ident = label - else: - volume_ident = "_unknown" - return volume_ident - - def escrow(self, directory, backupPassphrase): - log.debug("escrow: escrowVolume start for %s" % self.device) - if volume_key is None: - raise LUKSError("Missing key escrow support libraries") - - vol = volume_key.Volume.open(self.device) - volume_ident = self._escrowVolumeIdent(vol) - - ui = volume_key.UI() - # This callback is not expected to be used, let it always fail - ui.generic_cb = lambda unused_prompt, unused_echo: None - def known_passphrase_cb(unused_prompt, failed_attempts): - if failed_attempts == 0: - return self.__passphrase - return None - ui.passphrase_cb = known_passphrase_cb - - log.debug("escrow: getting secret") - vol.get_secret(volume_key.SECRET_DEFAULT, ui) - log.debug("escrow: creating packet") - default_packet = vol.create_packet_assymetric_from_cert_data \ - (volume_key.SECRET_DEFAULT, self.escrow_cert, ui) - log.debug("escrow: packet created") - with open("%s/%s-escrow" % (directory, volume_ident), "wb") as f: - f.write(default_packet) - log.debug("escrow: packet written") - - if self.add_backup_passphrase: - log.debug("escrow: adding backup passphrase") - vol.add_secret(volume_key.SECRET_PASSPHRASE, backupPassphrase) - log.debug("escrow: creating backup packet") - backup_passphrase_packet = \ - vol.create_packet_assymetric_from_cert_data \ - (volume_key.SECRET_PASSPHRASE, self.escrow_cert, ui) - log.debug("escrow: backup packet created") - with open("%s/%s-escrow-backup-passphrase" % - (directory, volume_ident), "wb") as f: - f.write(backup_passphrase_packet) - log.debug("escrow: backup packet written") - - log.debug("escrow: escrowVolume done for %s" % repr(self.device)) - - -register_device_format(LUKS) - diff --git a/pyanaconda/storage/formats/lvmpv.py b/pyanaconda/storage/formats/lvmpv.py deleted file mode 100644 index d804711fa..000000000 --- a/pyanaconda/storage/formats/lvmpv.py +++ /dev/null @@ -1,146 +0,0 @@ -# lvmpv.py -# Device format classes for anaconda's storage configuration module. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -import os - -from ..storage_log import log_method_call -from parted import PARTITION_LVM -from ..errors import * -from ..devicelibs import lvm -from . import DeviceFormat, register_device_format - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - - -class LVMPhysicalVolume(DeviceFormat): - """ An LVM physical volume. """ - _type = "lvmpv" - _name = "physical volume (LVM)" - _udevTypes = ["LVM2_member"] - partedFlag = PARTITION_LVM - _formattable = True # can be formatted - _supported = True # is supported - _linuxNative = True # for clearpart - _minSize = lvm.LVM_PE_SIZE * 2 # one for metadata and one for data - _packages = ["lvm2"] # required packages - - def __init__(self, *args, **kwargs): - """ Create an LVMPhysicalVolume instance. - - Keyword Arguments: - - device -- path to the underlying device - uuid -- this PV's uuid (not the VG uuid) - vgName -- the name of the VG this PV belongs to - vgUuid -- the UUID of the VG this PV belongs to - peStart -- offset of first physical extent - exists -- indicates whether this is an existing format - - """ - log_method_call(self, *args, **kwargs) - DeviceFormat.__init__(self, *args, **kwargs) - self.vgName = kwargs.get("vgName") - self.vgUuid = kwargs.get("vgUuid") - # liblvm may be able to tell us this at some point, even - # for not-yet-created devices - self.peStart = kwargs.get("peStart", lvm.LVM_PE_START) # in MB - - self.inconsistentVG = False - - def __repr__(self): - s = DeviceFormat.__repr__(self) - s += (" vgName = %(vgName)s vgUUID = %(vgUUID)s" - " peStart = %(peStart)s" % - {"vgName": self.vgName, "vgUUID": self.vgUuid, - "peStart": self.peStart}) - return s - - @property - def dict(self): - d = super(LVMPhysicalVolume, self).dict - d.update({"vgName": self.vgName, "vgUUID": self.vgUuid, - "peStart": self.peStart}) - return d - - def probe(self): - """ Probe for any missing information about this device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise PhysicalVolumeError("format has not been created") - - #info = lvm.pvinfo(self.device) - #self.vgName = info['vg_name'] - #self.vgUuid = info['vg_uuid'] - - def create(self, *args, **kwargs): - """ Create the format. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - - try: - DeviceFormat.create(self, *args, **kwargs) - # Consider use of -Z|--zero - # -f|--force or -y|--yes may be required - - # lvm has issues with persistence of metadata, so here comes the - # hammer... - DeviceFormat.destroy(self, *args, **kwargs) - - lvm.pvcreate(self.device) - except Exception: - raise - else: - self.exists = True - self.notifyKernel() - - def destroy(self, *args, **kwargs): - """ Destroy the format. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise PhysicalVolumeError("format has not been created") - - if self.status: - raise PhysicalVolumeError("device is active") - - # FIXME: verify path exists? - try: - lvm.pvremove(self.device) - except LVMError: - DeviceFormat.destroy(self, *args, **kwargs) - - self.exists = False - self.notifyKernel() - - @property - def status(self): - # XXX hack - return (self.exists and self.vgName and - os.path.isdir("/dev/mapper/%s" % self.vgName)) - -register_device_format(LVMPhysicalVolume) - diff --git a/pyanaconda/storage/formats/mdraid.py b/pyanaconda/storage/formats/mdraid.py deleted file mode 100644 index 9d1e26eed..000000000 --- a/pyanaconda/storage/formats/mdraid.py +++ /dev/null @@ -1,120 +0,0 @@ -# mdraid.py -# Device format classes for anaconda's storage configuration module. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -import os - -from ..storage_log import log_method_call -from parted import PARTITION_RAID -from ..errors import * -from ..devicelibs import mdraid -from . import DeviceFormat, register_device_format -from ..flags import flags - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - - -class MDRaidMember(DeviceFormat): - """ An mdraid member disk. """ - _type = "mdmember" - _name = "software RAID" - _udevTypes = ["linux_raid_member"] - partedFlag = PARTITION_RAID - _formattable = True # can be formatted - _supported = True # is supported - _linuxNative = True # for clearpart - _packages = ["mdadm"] # required packages - - def __init__(self, *args, **kwargs): - """ Create a MDRaidMember instance. - - Keyword Arguments: - - device -- path to underlying device - uuid -- this member device's uuid - mdUuid -- the uuid of the array this device belongs to - exists -- indicates whether this is an existing format - - """ - log_method_call(self, *args, **kwargs) - DeviceFormat.__init__(self, *args, **kwargs) - self.mdUuid = kwargs.get("mdUuid") - self.raidMinor = None - - #self.probe() - self.biosraid = kwargs.get("biosraid") - - def __repr__(self): - s = DeviceFormat.__repr__(self) - s += (" mdUUID = %(mdUUID)s biosraid = %(biosraid)s" % - {"mdUUID": self.mdUuid, "biosraid": self.biosraid}) - return s - - @property - def dict(self): - d = super(MDRaidMember, self).dict - d.update({"mdUUID": self.mdUuid, "biosraid": self.biosraid}) - return d - - def probe(self): - """ Probe for any missing information about this format. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise MDMemberError("format does not exist") - - info = mdraid.mdexamine(self.device) - if self.uuid is None: - self.uuid = info['uuid'] - if self.raidMinor is None: - self.raidMinor = info['mdMinor'] - - def destroy(self, *args, **kwargs): - if not self.exists: - raise MDMemberError("format does not exist") - - if not os.access(self.device, os.W_OK): - raise MDMemberError("device path does not exist") - - mdraid.mddestroy(self.device) - self.exists = False - - @property - def status(self): - # XXX hack -- we don't have a nice way to see if the array is active - return False - - @property - def hidden(self): - return (self._hidden or self.biosraid) - -# nodmraid -> Wether to use BIOS RAID or not -# Note the anaconda cmdline has not been parsed yet when we're first imported, -# so we can not use flags.dmraid here -if not flags.noiswmd and flags.dmraid: - MDRaidMember._udevTypes.append("isw_raid_member") - -register_device_format(MDRaidMember) - diff --git a/pyanaconda/storage/formats/multipath.py b/pyanaconda/storage/formats/multipath.py deleted file mode 100644 index 01d69ee3e..000000000 --- a/pyanaconda/storage/formats/multipath.py +++ /dev/null @@ -1,94 +0,0 @@ -# multipath.py -# multipath device formats -# -# Copyright (C) 2009 Red Hat, Inc. -# -# 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/>. -# -# Any Red Hat trademarks that are incorporated in the source code or -# documentation are not subject to the GNU General Public License and -# may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Peter Jones <pjones@redhat.com> -# - -from ..storage_log import log_method_call -from ..errors import * -from . import DeviceFormat, register_device_format - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - -class MultipathMember(DeviceFormat): - """ A multipath member disk. """ - _type = "multipath_member" - _name = "multipath member device" - _udev_types = ["multipath_member"] - _formattable = False # can be formatted - _supported = True # is supported - _linuxNative = False # for clearpart - _packages = ["device-mapper-multipath"] # required packages - _resizable = False # can be resized - _maxSize = 0 # maximum size in MB - _minSize = 0 # minimum size in MB - _hidden = True # hide devices with this formatting? - - def __init__(self, *args, **kwargs): - """ Create a DeviceFormat instance. - - Keyword Arguments: - - device -- path to the underlying device - uuid -- this format's UUID - exists -- indicates whether this is an existing format - - On initialization this format is like DeviceFormat - - """ - log_method_call(self, *args, **kwargs) - DeviceFormat.__init__(self, *args, **kwargs) - - # Initialize the attribute that will hold the block object. - self._member = None - - def __repr__(self): - s = DeviceFormat.__repr__(self) - s += (" member = %(member)r" % {"member": self.member}) - return s - - def _getMember(self): - return self._member - - def _setMember(self, member): - self._member = member - - member = property(lambda s: s._getMember(), - lambda s,m: s._setMember(m)) - - def create(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - raise MultipathMemberError("creation of multipath members is non-sense") - - def destroy(self, *args, **kwargs): - log_method_call(self, device=self.device, - type=self.type, status=self.status) - raise MultipathMemberError("destruction of multipath members is non-sense") - -register_device_format(MultipathMember) - diff --git a/pyanaconda/storage/formats/prepboot.py b/pyanaconda/storage/formats/prepboot.py deleted file mode 100644 index dd2cf8c82..000000000 --- a/pyanaconda/storage/formats/prepboot.py +++ /dev/null @@ -1,87 +0,0 @@ -# prepboot.py -# Format class for PPC PReP Boot. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -from ..errors import * -from .. import platform -from . import DeviceFormat, register_device_format -from parted import PARTITION_PREP -import os -import logging -log = logging.getLogger("storage") - -class PPCPRePBoot(DeviceFormat): - """ Generic device format. """ - _type = "prepboot" - _name = "PPC PReP Boot" - _udevTypes = [] - partedFlag = PARTITION_PREP - _formattable = True # can be formatted - _linuxNative = True # for clearpart - _maxSize = 10 # maximum size in MB - _minSize = 4 # minimum size in MB - - def __init__(self, *args, **kwargs): - """ Create a PRePBoot instance. - - Keyword Arguments: - - device -- path to the underlying device - exists -- indicates whether this is an existing format - - """ - DeviceFormat.__init__(self, *args, **kwargs) - - def create(self, *args, **kwargs): - if self.exists: - raise FSError("PReP Boot format already exists") - - DeviceFormat.create(self, *args, **kwargs) - - try: - fd = os.open(self.device, os.O_RDWR) - length = os.lseek(fd, 0, os.SEEK_END) - os.lseek(fd, 0, os.SEEK_SET) - buf = '\0' * 1024 * 1024 - while length > 0: - if length >= len(buf): - os.write(fd, buf) - length -= len(buf) - else: - buf = '0' * length - os.write(fd, buf) - length = 0 - os.close(fd) - except OSError as e: - log.error("error zeroing out %s: %s" % (self.device, e)) - if fd: - os.close(fd) - - @property - def status(self): - return False - - @property - def supported(self): - return isinstance(platform.platform, platform.IPSeriesPPC) - -register_device_format(PPCPRePBoot) - diff --git a/pyanaconda/storage/formats/swap.py b/pyanaconda/storage/formats/swap.py deleted file mode 100644 index 903fe6e2c..000000000 --- a/pyanaconda/storage/formats/swap.py +++ /dev/null @@ -1,171 +0,0 @@ -# swap.py -# Device format classes for anaconda's storage configuration module. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions of -# the GNU General Public License v.2, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the -# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the -# source code or documentation are not subject to the GNU General Public -# License and may only be used or replicated with the express permission of -# Red Hat, Inc. -# -# Red Hat Author(s): Dave Lehman <dlehman@redhat.com> -# - -from parted import PARTITION_SWAP, fileSystemType -from ..storage_log import log_method_call -from ..errors import * -from ..util import numeric_type -from ..devicelibs import swap -from . import DeviceFormat, register_device_format - -import gettext -_ = lambda x: gettext.ldgettext("anaconda", x) - -import logging -log = logging.getLogger("storage") - - -class SwapSpace(DeviceFormat): - """ Swap space """ - _type = "swap" - _name = None - _udevTypes = ["swap"] - partedFlag = PARTITION_SWAP - partedSystem = fileSystemType["linux-swap(v1)"] - _formattable = True # can be formatted - _supported = True # is supported - _linuxNative = True # for clearpart - - #see rhbz#744129 for details - _maxSize = 128 * 1024 - - def __init__(self, *args, **kwargs): - """ Create a SwapSpace instance. - - Keyword Arguments: - - device -- path to the underlying device - uuid -- this swap space's uuid - label -- this swap space's label - priority -- this swap space's priority - exists -- indicates whether this is an existing format - - """ - log_method_call(self, *args, **kwargs) - DeviceFormat.__init__(self, *args, **kwargs) - - self.priority = kwargs.get("priority") - self.label = kwargs.get("label") - - def __repr__(self): - s = DeviceFormat.__repr__(self) - s += (" priority = %(priority)s label = %(label)s" % - {"priority": self.priority, "label": self.label}) - return s - - @property - def dict(self): - d = super(SwapSpace, self).dict - d.update({"priority": self.priority, "label": self.label}) - return d - - def _setPriority(self, priority): - if priority is None: - self._priority = None - return - - if not isinstance(priority, int) or not 0 <= priority <= 32767: - raise ValueError("swap priority must be an integer between 0 and 32767") - - self._priority = priority - - def _getPriority(self): - return self._priority - - priority = property(_getPriority, _setPriority, - doc="The priority of the swap device") - - def _getOptions(self): - opts = "" - if self.priority is not None: - opts += "pri=%d" % self.priority - - return opts - - def _setOptions(self, opts): - if not opts: - self.priority = None - return - - for option in opts.split(","): - (opt, equals, arg) = option.partition("=") - if equals and opt == "pri": - try: - self.priority = int(arg) - except ValueError: - log.info("invalid value for swap priority: %s" % arg) - - options = property(_getOptions, _setOptions, - doc="The swap device's fstab options string") - - @property - def status(self): - """ Device status. """ - return self.exists and swap.swapstatus(self.device) - - def setup(self, *args, **kwargs): - """ Open, or set up, a device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise SwapSpaceError("format has not been created") - - if self.status: - return - - DeviceFormat.setup(self, *args, **kwargs) - swap.swapon(self.device, priority=self.priority) - - def teardown(self, *args, **kwargs): - """ Close, or tear down, a device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - if not self.exists: - raise SwapSpaceError("format has not been created") - - if self.status: - swap.swapoff(self.device) - - def create(self, *args, **kwargs): - """ Create the device. """ - log_method_call(self, device=self.device, - type=self.type, status=self.status) - force = kwargs.get("force") - if not force and self.exists: - raise SwapSpaceError("format already exists") - - if force: - self.teardown() - elif self.status: - raise SwapSpaceError("device exists and is active") - - try: - DeviceFormat.create(self, *args, **kwargs) - swap.mkswap(self.device, label=self.label) - except Exception: - raise - else: - self.exists = True - self.notifyKernel() - -register_device_format(SwapSpace) - |