]> git.ipfire.org Git - people/ms/ipfire-3.x.git/commitdiff
Daily checkin.
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 10 May 2009 20:35:46 +0000 (22:35 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 30 Jul 2009 18:28:07 +0000 (20:28 +0200)
.gitignore
lfs/python-parted
src/pomona/exception.py
src/pomona/log.py
src/pomona/partition.py
src/pomona/storage/__init__.py
src/pomona/storage/devices.py
src/pomona/storage/devicetree.py
src/pomona/storage/formats/__init__.py
src/pomona/storage/formats/swap.py
src/pomona/text.py

index 18cdbb70ee5637cb8ea6dfd71173ba001e2c712b..690c03f995fbd0c3a4e8b8b3974a8f23c9ae3e09 100644 (file)
@@ -16,3 +16,4 @@
 /*.iso
 /*.tar.gz
 *~
+*.py[co]
index a66991cbe4a90b6b7bd44928689c919977fba16d..557387ff4e99631c2440ed00f960d10ac1c00a65 100644 (file)
@@ -25,7 +25,7 @@
 include Config
 
 PKG_NAME   = pyparted
-PKG_VER    = 2.0.10
+PKG_VER    = 2.0.12
 
 THISAPP    = $(PKG_NAME)-$(PKG_VER)
 DL_FILE    = $(THISAPP).tar.gz
index 52ad9bf799fafda1639f0a5a57ffd2eb93af13db..36fd2b004e994057332887fc48fb3bd0bba3fc21 100644 (file)
@@ -127,6 +127,8 @@ def handleException(installer, (type, value, tb)):
     # restore original exception handler
     sys.excepthook = sys.__excepthook__
 
+    installer.log.error("Exception occured. Read more in /tmp/instdump.txt.")
+
     # get traceback information
     list = formatException(type, value, tb)
     text = string.joinfields(list, "")
index 84608939ab544a19d08bc1daf9e9308a048e0a20..aee3e5d5fc10a4290899e9ab305f991c500133c6 100644 (file)
@@ -12,21 +12,27 @@ class Logger:
 
     def critical(self, msg):
         self.logfile.write(self.logline % (self.time(), "CRITICAL", msg,))
+        self.flush()
 
     def info(self, msg):
         self.logfile.write(self.logline % (self.time(), "INFO",     msg,))
+        self.flush()
 
     def debug(self, msg):
         self.logfile.write(self.logline % (self.time(), "DEBUG",    msg,))
+        self.flush()
 
     def error(self, msg):
         self.logfile.write(self.logline % (self.time(), "ERROR",    msg,))
+        self.flush()
 
     def warning(self, msg):
         self.logfile.write(self.logline % (self.time(), "WARNING",  msg,))
+        self.flush()
 
     def stdout(self, msg):
         self.logfile.write(self.logline % (self.time(), "STDOUT",   msg,))
+        self.flush()
         print msg
 
     def time(self):
@@ -34,3 +40,6 @@ class Logger:
 
     def __del__(self):
         self.logfile.close()
+
+    def flush(self):
+        self.logfile.flush()
index 8695263cc9c4f328be9fd9ef94e06607d67d13f2..843dba8945090d51a90f7b83e370d31612c62e0b 100644 (file)
@@ -2,6 +2,8 @@
 
 from snack import *
 
+from storage.deviceaction import *
+import storage
 import storage.formats as formats
 from storage.devicelibs.lvm import safeLvmName
 
@@ -161,6 +163,7 @@ class PartitionWindow(object):
             return
         
         row = 0
+        actions = []
         
         if not device.exists:
             tstr = _("Add Partition")
@@ -168,6 +171,12 @@ class PartitionWindow(object):
             tstr = _("Edit Partition")
         grid = GridForm(self.screen, tstr, 1, 6)
         
+        if device.exists:
+            if device.format.exists and getattr(device.format, "label", None):
+                lbl = Label("%s %s" % (_("Original File System Label:"), device.format.label))
+                grid.add(lbl, 0, row)
+                row += 1
+        
         (mountgrid, mountpoint) = self.makeMountPoint(device)
         grid.add(mountgrid, 0, row)
         row += 1
@@ -176,13 +185,15 @@ class PartitionWindow(object):
             subgrid1 = Grid(2, 1)
         
             (devgrid, drivelist) = self.makeDriveList(device)
-            subgrid1.setField(devgrid, 0, 0, (0,1,0,0), growx=1)
+            subgrid1.setField(devgrid, 0, 0)
             
             (fsgrid, fstype) = self.makeFileSystemList(device)
-            subgrid1.setField(fsgrid, 1, 0)
+            subgrid1.setField(fsgrid, 1, 0, (1,0,0,0), growx=1)
             
             grid.add(subgrid1, 0, row, (0,1,0,0), growx=1)
             row += 1
+        else:
+            pass
         
         bb = ButtonBar(self.screen, (TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON))
         grid.add(bb, 0, row, (0,1,0,0), growx = 1)
@@ -202,10 +213,14 @@ class PartitionWindow(object):
 
             if device.format:
                 device.format.mountpoint = mountpoint.value()
+                
+            if not device.exists:
+                actions.append(ActionCreateDevice(self.installer, device))
 
             break
         
         self.screen.popWindow()
+        return actions
 
     def editVG(self, device):
         if not device.exists:
@@ -251,14 +266,30 @@ class PartitionWindow(object):
             self.installer.intf.messageWindow(_("Unable To Edit"),
                                               _("You must first select a partition to edit."))
             return
+        
+        reason = self.storage.deviceImmutable(device)
+        if reason:
+            self.installer.intf.messageWindow(_("Unable To Edit"),
+                                              _("You cannot edit this device:\n\n%s")
+                                              % reason,)
+            return
 
-        self.editPart(device)
+        actions = None
+        if device.type == "mdarray":
+            pass #self.editRaidArray(device)
+        elif device.type == "lvmvg":
+            actions = self.editVG(device)
+        elif device.type == "lvmlv":
+            actions = self.editLV(device)
+        elif isinstance(device, storage.devices.PartitionDevice):
+            actions = self.editPart(device)
+        
+        for action in actions:
+            self.storage.devicetree.registerAction(action)
 
     def deleteCb(self):
         device = self.lb.current()
-        
-        self.installer.log.debug("%s" % device.type)
-        
+
         if not device:
             self.installer.intf.messageWindow(_("Unable To Delete"),
                                               _("You must first select a partition to delete."))
@@ -280,7 +311,7 @@ class PartitionWindow(object):
         self.screen = self.installer.intf.screen
         self.storage = self.installer.ds.storage
         
-        self.installer.intf.setHelpline(_("F1-Help  F2-New  F3-Edit  F4-Delete  F5-Reset  F12-OK"))
+        self.installer.intf.setHelpline(_("F2-New  F3-Edit  F4-Delete  F5-Reset  F12-OK"))
         
         self.g = GridForm(self.screen, _("Partitioning"), 1, 5)
         self.lb = CListbox(height=10, cols=4,
index 9b30223358bc8efb48d59028f20622c28e156845..2a0da0b8da5df1909a2c26c459da549cefd88d69 100644 (file)
@@ -415,6 +415,70 @@ class Storage(object):
 
         return lvtemplate
 
+    def deviceImmutable(self, device):
+        """ Return any reason the device cannot be modified/removed.
+
+            Return False if the device can be removed.
+
+            Devices that cannot be removed include:
+
+                - protected partitions
+                - devices that are part of an md array or lvm vg
+                - extended partition containing logical partitions that
+                  meet any of the above criteria
+
+        """
+        if not isinstance(device, Device):
+            raise ValueError("arg1 (%s) must be a Device instance" % device)
+
+        if device.name in self.protectedDisks:
+            return _("This partition is holding the data for the hard "
+                      "drive install.")
+        elif device.format.type == "mdmember":
+            for array in self.mdarrays:
+                if array.dependsOn(device):
+                    if array.minor is not None:
+                        return _("This device is part of the RAID "
+                                 "device %s.") % (array.path,)
+                    else:
+                        return _("This device is part of a RAID device.")
+        elif device.format.type == "lvmpv":
+            for vg in self.vgs:
+                if vg.dependsOn(device):
+                    if vg.name is not None:
+                        return _("This device is part of the LVM "
+                                 "volume group '%s'.") % (vg.name,)
+                    else:
+                        return _("This device is part of a LVM volume "
+                                 "group.")
+        elif device.format.type == "luks":
+            try:
+                luksdev = self.devicetree.getChildren(device)[0]
+            except IndexError:
+                pass
+            else:
+                return self.deviceImmutable(luksdev)
+        elif isinstance(device, PartitionDevice) and device.isExtended:
+            reasons = {}
+            for dep in self.deviceDeps(device):
+                reason = self.deviceImmutable(dep)
+                if reason:
+                    reasons[dep.path] = reason
+            if reasons:
+                msg =  _("This device is an extended partition which "
+                         "contains logical partitions that cannot be "
+                         "deleted:\n\n")
+                for dev in reasons:
+                    msg += "%s: %s" % (dev, reasons[dev])
+                return msg
+
+        for i in self.devicetree.immutableDevices:
+            if i[0] == device.name:
+                return i[1]
+
+        return False
+
+
 class FSSet(object):
     """ A class to represent a set of filesystems. """
     def __init__(self, installer):
index 0d952a7f018376e2860543d7a243ecde2cd625d4..3628054818e196c5d08cef1a7040b83acce09fbe 100644 (file)
@@ -1,8 +1,11 @@
 #/usr/bin/python
 
+import copy
 import math
 import parted
+import _ped
 
+from errors import *
 from formats import get_device_format_class, getFormat
 from udev import *
 from util import notify_kernel, numeric_type
@@ -80,6 +83,25 @@ class Device(object):
         for parent in self.parents:
             parent.addChild()
 
+    def __deepcopy__(self, memo):
+        """ Create a deep copy of a Device 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 = ('partedDisk', '_partedDevice',
+                             '_partedPartition', '_origPartedDisk',
+                             '_raidSet', 'installer', 'screen')
+        for (attr, value) in self.__dict__.items():
+            if attr in shallow_copy_attrs:
+                setattr(new, attr, copy.copy(value))
+            else:
+                setattr(new, attr, copy.deepcopy(value, memo))
+
+        return new
+
     def removeChild(self):
         self.kids -= 1
 
@@ -1009,6 +1031,57 @@ class PartitionDevice(StorageDevice):
         else:
             return self.format.maxSize
 
+class OpticalDevice(StorageDevice):
+    """ An optical drive, eg: cdrom, dvd+r, &c.
+
+        XXX Is this useful?
+    """
+    _type = "cdrom"
+
+    def __init__(self, installer, name, major=None, minor=None, exists=None,
+                 format=None, parents=None, sysfsPath=''):
+        StorageDevice.__init__(self, installer, name, format=format,
+                               major=major, minor=minor, exists=True,
+                               parents=parents, sysfsPath=sysfsPath)
+
+    @property
+    def mediaPresent(self):
+        """ Return a boolean indicating whether or not the device contains
+            media.
+        """
+        if not self.exists:
+            raise DeviceError("device has not been created", self.path)
+
+        try:
+            fd = os.open(self.path, os.O_RDONLY)
+        except OSError as e:
+            # errno 123 = No medium found
+            if e.errno == 123:
+                return False
+            else:
+                return True
+        else:
+            os.close(fd)
+            return True
+
+    def eject(self):
+        """ Eject the drawer. """
+        #import _isys
+
+        if not self.exists:
+            raise DeviceError("device has not been created", self.path)
+
+        # Make a best effort attempt to do the eject.  If it fails, it's not
+        # critical.
+        fd = os.open(self.path, os.O_RDONLY | os.O_NONBLOCK)
+
+        #try:
+        #    _isys.ejectcdrom(fd)
+        #except SystemError as e:
+        #    log.warning("error ejecting cdrom %s: %s" % (self.name, e))
+
+        os.close(fd)
+
 class DMDevice(StorageDevice):
     """ A device-mapper device """
     _type = "dm"
index ff75014153d4a2962f66aeec3403a9c9637585b5..8d3a1e17eeec157b69de02cd1d596a173ab2c130 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
 import os
+import block
 
 import formats
 
@@ -18,6 +19,7 @@ class DeviceTree:
         self._actions = []
 
         self._ignoredDisks = []
+        self.immutableDevices = []
         for disk in self.storage.ignoredDisks:
             self.addIgnoredDisk(disk)
 
@@ -251,46 +253,45 @@ class DeviceTree:
         sysfs_path = udev_device_get_sysfs_path(info)
 
         if self.isIgnored(info):
-            #self.installer.log.debug("Ignoring %s (%s)" % (name, sysfs_path))
+            self.installer.log.debug("Ignoring %s (%s)" % (name, sysfs_path))
             return
 
-        #self.installer.log.debug("Scanning %s (%s)..." % (name, sysfs_path))
+        self.installer.log.debug("Scanning %s (%s)..." % (name, sysfs_path))
         device = self.getDeviceByName(name)
 
         #
         # The first step is to either look up or create the device
         #
         if udev_device_is_dm(info):
-            pass
-        #    # try to look up the device
-        #    if device is None and uuid:
-        #        # try to find the device by uuid
-        #        device = self.getDeviceByUuid(uuid)
-        #
-        #    if device is None:
-        #        device = self.addUdevDMDevice(info)
-        #elif udev_device_is_md(info):
-        #    if device is None and uuid:
-        #        # try to find the device by uuid
-        #        device = self.getDeviceByUuid(uuid)
-        #
-        #    if device is None:
-        #        device = self.addUdevMDDevice(info)
-        #elif udev_device_is_cdrom(info):
-        #    if device is None:
-        #        device = self.addUdevOpticalDevice(info)
-        #elif udev_device_is_dmraid(info):
+            # try to look up the device
+            if device is None and uuid:
+                # try to find the device by uuid
+                device = self.getDeviceByUuid(uuid)
+        
+            if device is None:
+                device = self.addUdevDMDevice(info)
+        elif udev_device_is_md(info):
+            if device is None and uuid:
+                # try to find the device by uuid
+                device = self.getDeviceByUuid(uuid)
+        
+            if device is None:
+                device = self.addUdevMDDevice(info)
+        elif udev_device_is_cdrom(info):
+            if device is None:
+                device = self.addUdevOpticalDevice(info)
+        elif udev_device_is_dmraid(info):
             # This is special handling to avoid the "unrecognized disklabel"
             # code since dmraid member disks won't have a disklabel. We
             # use a StorageDevice because DiskDevices need disklabels.
             # Quite lame, but it doesn't matter much since we won't use
             # the StorageDevice instances for anything.
-        #    if device is None:
-        #        device = StorageDevice(name,
-        #                        major=udev_device_get_major(info),
-        #                        minor=udev_device_get_minor(info),
-        #                        sysfsPath=sysfs_path, exists=True)
-        #        self._addDevice(device)
+            if device is None:
+                device = StorageDevice(name,
+                                major=udev_device_get_major(info),
+                                minor=udev_device_get_minor(info),
+                                sysfsPath=sysfs_path, exists=True)
+                self._addDevice(device)
         elif udev_device_is_disk(info):
             if device is None:
                 device = self.addUdevDiskDevice(info)
@@ -299,7 +300,7 @@ class DeviceTree:
                 device = self.addUdevPartitionDevice(info)
 
         # now handle the device's formatting
-        #self.handleUdevDeviceFormat(info, device)
+        self.handleUdevDeviceFormat(info, device)
 
     def addUdevDiskDevice(self, info):
         name = udev_device_get_name(info)
@@ -358,6 +359,165 @@ class DeviceTree:
         self._addDevice(device)
         return device
 
+    def addUdevOpticalDevice(self, info):
+        # Looks like if it has ID_INSTANCE=0:1 we can ignore it.
+        device = OpticalDevice(self.installer, udev_device_get_name(info),
+                               major=udev_device_get_major(info),
+                               minor=udev_device_get_minor(info),
+                               sysfsPath=udev_device_get_sysfs_path(info))
+        self._addDevice(device)
+        return device
+
+    def handleUdevDeviceFormat(self, info, device):
+        #log.debug("%s" % info)
+        name = udev_device_get_name(info)
+        sysfs_path = udev_device_get_sysfs_path(info)
+        uuid = udev_device_get_uuid(info)
+        label = udev_device_get_label(info)
+        format_type = udev_device_get_format(info)
+
+        format = None
+        if (not device) or (not format_type) or device.format.type:
+            # this device has no formatting or it has already been set up
+            # FIXME: this probably needs something special for disklabels
+            self.installer.log.debug("no type or existing type for %s, bailing" % (name,))
+            return
+
+        # set up the common arguments for the format constructor
+        args = [format_type]
+        kwargs = {"uuid": uuid,
+                  "label": label,
+                  "device": device.path,
+                  "exists": True}
+
+        # set up type-specific arguments for the format constructor
+        if format_type == "crypto_LUKS":
+            # luks/dmcrypt
+            kwargs["name"] = "luks-%s" % uuid
+        elif format_type == "linux_raid_member":
+            # mdraid
+            try:
+                kwargs["mdUuid"] = udev_device_get_md_uuid(info)
+            except KeyError:
+                self.installer.log.debug("mdraid member %s has no md uuid" % name)
+        elif format_type == "LVM2_member":
+            # lvm
+            try:
+                kwargs["vgName"] = udev_device_get_vg_name(info)
+            except KeyError as e:
+                self.installer.log.debug("PV %s has no vg_name" % name)
+            try:
+                kwargs["vgUuid"] = udev_device_get_vg_uuid(info)
+            except KeyError:
+                self.installer.log.debug("PV %s has no vg_uuid" % name)
+            try:
+                kwargs["peStart"] = udev_device_get_pv_pe_start(info)
+            except KeyError:
+                self.installer.log.debug("PV %s has no pe_start" % name)
+
+        try:
+            self.installer.log.debug("type detected on '%s' is '%s'" % (name, format_type,))
+            device.format = formats.getFormat(format_type, *args, **kwargs)
+        except FSError, e:
+            self.installer.log.debug("type '%s' on '%s' invalid, assuming no format - %s" %
+                      (format_type, name, e,))
+            device.format = formats.DeviceFormat(self.installer)
+            return
+
+        #
+        # now do any special handling required for the device's format
+        #
+        #if device.format.type == "luks":
+        #    self.handleUdevLUKSFormat(info, device)
+        #elif device.format.type == "mdmember":
+        #    self.handleUdevMDMemberFormat(info, device)
+        #elif device.format.type == "dmraidmember":
+        #    self.handleUdevDMRaidMemberFormat(info, device)
+        #elif device.format.type == "lvmpv":
+        #    self.handleUdevLVMPVFormat(info, device)
+
+    def handleUdevDMRaidMemberFormat(self, info, device):
+        name = udev_device_get_name(info)
+        sysfs_path = udev_device_get_sysfs_path(info)
+        uuid = udev_device_get_uuid(info)
+        major = udev_device_get_major(info)
+        minor = udev_device_get_minor(info)
+
+        def _all_ignored(rss):
+            retval = True
+            for rs in rss:
+                if rs.name not in self._ignoredDisks:
+                    retval = False
+                    break
+            return retval
+
+        # Have we already created the DMRaidArrayDevice?
+        rss = block.getRaidSetFromRelatedMem(uuid=uuid, name=name,
+                                            major=major, minor=minor)
+        if len(rss) == 0:
+            # we ignore the device in the hope that all the devices
+            # from this set will be ignored.
+            # FIXME: Can we reformat a raid device?
+            self.addIgnoredDisk(device.name)
+            return
+
+        # We ignore the device if all the rss are in self._ignoredDisks
+        if _all_ignored(rss):
+            self.addIgnoredDisk(device.name)
+            return
+
+        for rs in rss:
+            dm_array = self.getDeviceByName(rs.name)
+            if dm_array is not None:
+                # We add the new device.
+                dm_array._addDevice(device)
+            else:
+                # Activate the Raid set.
+                rs.activate(mknod=True)
+
+                # Create the DMRaidArray
+                if self.zeroMbr:
+                    cb = lambda: True
+                else:
+                    cb = lambda: questionInitializeDisk(self.intf,
+                                                        rs.name)
+
+                # Create the DMRaidArray
+                if not self.clearPartDisks or \
+                   rs.name in self.clearPartDisks:
+                    # if the disk contains protected partitions
+                    # we will not wipe the disklabel even if
+                    # clearpart --initlabel was specified
+                    initlabel = self.reinitializeDisks
+                    for protected in self.protectedPartitions:
+                        disk_name = re.sub(r'p\d+$', '', protected)
+                        if disk_name != protected and \
+                           disk_name == rs.name:
+                            initlabel = False
+                            break
+
+                try:
+                    dm_array = DMRaidArrayDevice(rs.name,
+                                                 raidSet=rs,
+                                                 parents=[device],
+                                                 initcb=cb,
+                                                 initlabel=initlabel)
+
+                    self._addDevice(dm_array)
+                    # Use the rs's object on the device.
+                    # pyblock can return the memebers of a set and the
+                    # device has the attribute to hold it.  But ATM we
+                    # are not really using it. Commenting this out until
+                    # we really need it.
+                    #device.format.raidmem = block.getMemFromRaidSet(dm_array,
+                    #        major=major, minor=minor, uuid=uuid, name=name)
+                except DeviceUserDeniedFormatError:
+                    # We should ignore the dmraid and its components
+                    self.addIgnoredDisk(rs.name)
+                    if _all_ignored(rss):
+                        self.addIgnoredDisk(device.name)
+                    rs.deactivate()
+
     def getDependentDevices(self, dep):
         """ Return a list of devices that depend on dep.
 
index b5d6f7746297b19015b43ba2369b0bb0e89bde62..b8fd9bc43af376682b67b0b12754aa9a3ba500dc 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
 import os
+import copy
 
 device_formats = {}
 def register_device_format(fmt_class):
@@ -99,7 +100,7 @@ def get_default_filesystem_type(boot=None):
 
     raise DeviceFormatError("None of %s is supported by your kernel" % ",".join(fstypes))
 
-class DeviceFormat:
+class DeviceFormat(object):
     """ Generic device format. """
     _type = None
     _name = "Unknown"
@@ -133,6 +134,18 @@ class DeviceFormat:
         self.options = kwargs.get("options")
         self._migrate = False
 
+    def __deepcopy__(self, memo):
+        new = self.__class__.__new__(self.__class__)
+        memo[id(self)] = new
+        shallow_copy_attrs = ('installer', 'screen')
+        for (attr, value) in self.__dict__.items():
+            if attr in shallow_copy_attrs:
+                setattr(new, attr, copy.copy(value))
+            else:
+                setattr(new, attr, copy.deepcopy(value, memo))
+
+        return new
+
     def _setOptions(self, options):
         self._options = options
 
index 289f9855578e649bc62e8db894b31af79c453e7e..487d3656bb4f5a1f0d94ad329040f03ec46f7049 100644 (file)
@@ -3,6 +3,7 @@
 from parted import PARTITION_SWAP
 
 from . import DeviceFormat, register_device_format
+from ..devicelibs import swap
 
 class SwapSpace(DeviceFormat):
     """ Swap space """
index a648b78f86dba22819965123f853d7ceeb1626e7..2719311164e3efde1f43db8b41936e52318d3923 100644 (file)
@@ -62,7 +62,7 @@ class ExceptionWindow(TextWindow):
 
     def run(self):
         self.rc = ButtonChoiceWindow(self.screen, _("Exception Occurred"),
-                                                  self.text, self.buttons)
+                                                  self.text, self.buttons, width=60)
 
     def getrc(self):
         return 0