[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PATCH] Add infrastructure for partition resizing



We add support to preexisting partitions to be resized by adjusting their
partition spec and then acting on the changes within the main partitioning
engine.  Keep track of what the maximum size for a preexisting partitition
is so that we don't have to check in the UI

Filesystems can claim to be resizable and implement the resize() method as
well as the getMinimumSize() method
---
 autopart.py     |   26 ++++++++++++++++++++++++--
 fsset.py        |   39 +++++++++++++++++++++++++++++++++++++++
 partRequests.py |   18 ++++++++++++++++++
 partitions.py   |    1 +
 4 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/autopart.py b/autopart.py
index 8886241..1492275 100644
--- a/autopart.py
+++ b/autopart.py
@@ -865,6 +865,23 @@ def setPreexistParts(diskset, requests):
         part = disk.next_partition()
         while part:
             if part.geom.start == request.start and part.geom.end == request.end:
+                # if the partition is being resized, we do that now
+                if request.targetSize is not None:
+                    startSec = part.geom.start
+                    endSec = part.geom.start + long(((request.targetSize * 1024L * 1024L) / disk.dev.sector_size)) - 1
+
+                    try:
+                        g = part.geom.duplicate()
+                        g.set_end(endSec)
+                        constraint = g.constraint_exact()
+                        part.set_geometry(constraint, startSec, endSec)
+                    except parted.error, msg:
+                        log.error("error setting geometry for partition %s: %s" %(partedUtils.get_partition_name(part), msg))
+                        raise PartitioningError, _("Error resizing partition %s.\n\n%s") %(partedUtils.get_partition_name(part), msg)
+
+                    if startSec != part.geom.start:
+                        raise PartitioningError, _("Start of partition %s was moved when resizing") %(partedUtils.get_partition_name(part),)
+
                 request.device = partedUtils.get_partition_name(part)
                 if request.fstype:
                     if request.fstype.getName() != request.origfstype.getName():
@@ -987,13 +1004,18 @@ def processPartitioning(diskset, requests, newParts):
     for request in requests.requests:
         if request.type == REQUEST_RAID:
             request.size = request.getActualSize(requests, diskset)
-        if request.type == REQUEST_VG:
+        elif request.type == REQUEST_VG:
             request.size = request.getActualSize(requests, diskset)
-        if request.type == REQUEST_LV:
+        elif request.type == REQUEST_LV:
 	    if request.grow:
 		request.setSize(request.getStartSize())
 	    else:
 		request.size = request.getActualSize(requests, diskset)
+        elif request.preexist:
+            # we need to keep track of the max size of preexisting partitions
+            # FIXME: we should also get the max size for LVs at some point
+            part = partedUtils.get_partition_by_name(diskset.disks, request.device)
+            request.maxResizeSize = partedUtils.getMaxAvailPartSizeMB(part)
 
 ##     print "disk layout after everything is done"
 ##     print diskset.diskState()
diff --git a/fsset.py b/fsset.py
index b50bb27..2830721 100644
--- a/fsset.py
+++ b/fsset.py
@@ -2,6 +2,7 @@
 # fsset.py: filesystem management
 #
 # Matt Wilson <msw redhat com>
+# Jeremy Katz <katzj redhat com>
 #
 # Copyright 2001-2007 Red Hat, Inc.
 #
@@ -177,10 +178,19 @@ class FileSystemType:
         self.extraFormatArgs = []
         self.maxLabelChars = 16
         self.packages = []
+        self.resizable = False
         self.supportsFsProfiles = False
         self.fsProfileSpecifier = None
         self.fsprofile = None
 
+    def isResizable(self):
+        return self.resizable
+    def resize(self, entry, size, progress, chroot='/'):
+        pass
+    def getMinimumSize(self, device):
+        log.warning("Unable to determinine minimal size for %s", device)
+        return 1
+
     def isKernelFS(self):
         """Returns True if this is an in-kernel pseudo-filesystem."""
         return False
@@ -1396,6 +1406,24 @@ MAILADDR root
             if bootPart:
                 del bootPart
 
+    def resizeFilesystems (self, chroot = '/', shrink = False, grow = False):
+        for entry in self.entries:
+            if not entry.fsystem or not entry.fsystem.isResizable():
+                continue
+            if entry.resizeTargetSize is None:
+                continue
+            if shrink and not (entry.resizeTargetSize < entry.resizeOrigSize):
+                continue
+            if grow and not (entry.resizeTargetSize > entry.resizeOrigSize):
+                continue
+            entry.fsystem.resize(entry, entry.resizeTargetSize,
+                                 self.progressWindow, chroot)
+
+    def shrinkFilesystems (self, chroot):
+        self.resizeFilesystems(chroot, shrink = True)
+    def growFilesystems (self, chroot):
+        self.resizeFilesystems(chroot, grow = True)
+
     def formatSwap (self, chroot, forceFormat=False):
         formatted = []
         notformatted = []
@@ -1847,6 +1875,8 @@ class FileSystemSetEntry:
         self.fsystem = fsystem
         self.origfsystem = origfsystem
         self.migrate = migrate
+        self.resizeTargetSize = None
+        self.resizeOrigSize = None
         self.options = options
         self.mountcount = 0
         self.label = None
@@ -1928,6 +1958,15 @@ class FileSystemSetEntry:
     def getMigrate (self):
         return self.migrate
 
+    def setResizeTarget (self, targetsize, size):
+        if not self.fsystem.isResizable() and targetsize is not None:
+            raise ValueError, "Can't set a resize target for a non-resizable filesystem"
+        self.resizeTargetSize = targetsize
+        self.resizeOrigSize = size
+
+    def getResizeTarget (self):
+        return self.targetsize
+
     def isMounted (self):
         return self.mountcount > 0
 
diff --git a/partRequests.py b/partRequests.py
index e113278..c5655e0 100644
--- a/partRequests.py
+++ b/partRequests.py
@@ -155,6 +155,9 @@ class RequestSpec:
         self.encryption = None
         """An optional LUKSDevice() describing block device encryption."""
 
+        self.targetSize = None
+        """Size to resize to"""
+
     def __str__(self):
         if self.fstype:
             fsname = self.fstype.getName()
@@ -212,6 +215,9 @@ class RequestSpec:
         if self.fslabel:
             entry.setLabel(self.fslabel)
 
+        if self.targetSize and self.fstype.isResizable():
+            entry.setResizeTarget(self.targetSize, self.size)
+
         return entry
 
     def setProtected(self, val):
@@ -576,6 +582,18 @@ class PreexistingPartitionSpec(PartitionSpec):
                                mountpoint = mountpoint, preexist = 1)
         self.type = REQUEST_PREEXIST
 
+        self.maxResizeSize = None
+        """Maximum size of this partition request"""
+
+    def getMaximumResizeMB(self):
+        if self.maxResizeSize is not None:
+            return self.maxResizeSize
+        log.warning("%s doesn't have a max size set" %(self.device,))
+        return MAX_PART_SIZE
+
+    def getMinimumResizeMB(self):
+        return self.fstype.getMinimumSize(self.device)
+
 class RaidRequestSpec(RequestSpec):
     """Request to represent RAID devices."""
     
diff --git a/partitions.py b/partitions.py
index 0dcb50c..b5ec7a3 100644
--- a/partitions.py
+++ b/partitions.py
@@ -202,6 +202,7 @@ class Partitions:
                                                              drive = drive,
                                                              format = format)
                 spec.device = fsset.PartedPartitionDevice(part).getDevice()
+                spec.maxResizeSize = partedUtils.getMaxAvailPartSizeMB(part)
 
                 # set label if makes sense
                 if ptype and ptype.isMountable() and \
-- 
1.5.3.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]