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

[PATCH] Backend code for logical volume resizing



---
 fsset.py        |   32 +++++++++++++++++++++++++++-----
 lvm.py          |   24 ++++++++++++++++++++----
 lvmErrors.py    |   10 ++++++++++
 packages.py     |    5 +++--
 partRequests.py |   23 +++++++++++++++++++++--
 partitions.py   |   23 ++++++++++++++++++++++-
 6 files changed, 103 insertions(+), 14 deletions(-)

diff --git a/fsset.py b/fsset.py
index 9a93726..867906c 100644
--- a/fsset.py
+++ b/fsset.py
@@ -1482,7 +1482,8 @@ MAILADDR root
             if bootPart:
                 del bootPart
 
-    def resizeFilesystems (self, chroot = '/', shrink = False, grow = False):
+    def resizeFilesystems (self, diskset, chroot = '/', shrink = False, grow = False):
+        todo = []
         for entry in self.entries:
             if not entry.fsystem or not entry.fsystem.isResizable():
                 continue
@@ -1492,13 +1493,34 @@ MAILADDR root
                 continue
             if grow and not (entry.resizeTargetSize > entry.resizeOrigSize):
                 continue
+            todo.append(entry)
+        if len(todo) == 0:
+            return
+
+        # we have to have lvm activated to be able to do resizes of LVs
+        active = lvm.vgcheckactive()
+        if not active:
+            diskset.startMPath()
+            diskset.startDmRaid()
+            diskset.startMdRaid()
+
+            lvm.vgscan()
+            lvm.vgactivate()
+
+        for entry in todo:
             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)
+        if not active:
+            lvm.vgdeactivate()
+            diskset.stopMPath()
+            diskset.stopDmRaid()
+            diskset.stopMdRaid()
+
+    def shrinkFilesystems (self, diskset, chroot):
+        self.resizeFilesystems(diskset, chroot, shrink = True)
+    def growFilesystems (self, diskset, chroot):
+        self.resizeFilesystems(diskset, chroot, grow = True)
 
     def formatSwap (self, chroot, forceFormat=False):
         formatted = []
diff --git a/lvm.py b/lvm.py
index e1ead92..4e14ac4 100644
--- a/lvm.py
+++ b/lvm.py
@@ -200,6 +200,22 @@ def lvremove(lvname, vgname):
     if rc:
         raise LVRemoveError(vgname, lvname)
 
+def lvresize(lvname, vgname, size):
+    global lvmDevicePresent
+    if flags.test or lvmDevicePresent == 0:
+        return
+
+    args = ["lvresize", "-An", "-L", "%dM" %(size,), "-v",
+            "/dev/%s/%s" %(vgname, lvname,)]
+
+    try:
+        rc = lvmExec(*args)
+    except:
+        rc = 1
+    if rc:
+        raise LVMResizeError(vgname, lvname)
+
+
 def vgcreate(vgname, PESize, nodes):
     """Creates a new volume group."
 
@@ -364,18 +380,18 @@ def vglist():
     vgs = []
     args = ["vgdisplay", "-C", "--noheadings", "--units", "b",
             "--nosuffix", "--separator", ":", "--options",
-            "vg_name,vg_size,vg_extent_size"
+            "vg_name,vg_size,vg_extent_size,vg_free"
            ]
     for line in lvmCapture(*args):
         try:
-            (vg, size, pesize) = line
+            (vg, size, pesize, free) = line
             size = long(math.floor(long(size) / (1024 * 1024)))
             pesize = long(pesize)/1024
+            free = math.floor(long(free) / (1024 * 1024))
         except:
             continue
         log.info("vg %s, size is %s, pesize is %s" %(vg, size, pesize))
-        vgs.append( (vg, size, pesize) )
-
+        vgs.append( (vg, size, pesize, free) )
     return vgs
 
 def partialvgs():
diff --git a/lvmErrors.py b/lvmErrors.py
index 3371c05..c69e9b5 100644
--- a/lvmErrors.py
+++ b/lvmErrors.py
@@ -59,6 +59,16 @@ class LVRemoveError(LvmError):
         return "lvremove of lv \"%s\" from vg \"%s\" failed\nLog:\n%s" % ( \
             self.lvname, self.vgname, self.log)
 
+class LVResizeError(LvmError):
+    def __init__(self, vgname, lvname):
+        self.vgname = vgname
+        self.lvname = lvname
+        self.log = self.getLvmOutput()
+
+    def __str__(self):
+        return "lvresize of lv \"%s\" from vg \"%s\" failed\nLog:\n%s" % ( \
+            self.lvname, self.vgname, self.log)
+
 class VGCreateError(LvmError):
     def __init__(self, vgname, PESize, nodes):
         self.vgname = vgname
diff --git a/packages.py b/packages.py
index 99f9a38..42dc12b 100644
--- a/packages.py
+++ b/packages.py
@@ -148,10 +148,11 @@ def turnOnFilesystems(anaconda):
                                        searchPath = 1)
             anaconda.id.partitions.doMetaDeletes(anaconda.id.diskset)
             anaconda.id.fsset.setActive(anaconda.id.diskset)
-            anaconda.id.fsset.shrinkFilesystems(anaconda.rootPath)
+            anaconda.id.fsset.shrinkFilesystems(anaconda.id.diskset, anaconda.rootPath)
             if not anaconda.id.fsset.isActive():
                 anaconda.id.diskset.savePartitions ()
-            anaconda.id.fsset.growFilesystems(anaconda.rootPath)
+                anaconda.id.partitions.doMetaResizes(anaconda.id.diskset)
+            anaconda.id.fsset.growFilesystems(anaconda.id.diskset, anaconda.rootPath)
             if not anaconda.id.fsset.volumesCreated:
                 anaconda.id.fsset.createLogicalVolumes(anaconda.rootPath)
             anaconda.id.fsset.formatSwap(anaconda.rootPath)
diff --git a/partRequests.py b/partRequests.py
index 84ff18a..a766404 100644
--- a/partRequests.py
+++ b/partRequests.py
@@ -795,6 +795,7 @@ class VolumeGroupRequestSpec(RequestSpec):
         self.physicalVolumes = physvols
         self.pesize = pesize
         self.preexist = preexist
+        self.free = 0
 
         # FIXME: this is a hack so that we can set the vg name automagically
         # with autopartitioning to not conflict with existing vgs
@@ -915,13 +916,15 @@ class LogicalVolumeRequestSpec(RequestSpec):
         self.grow = grow
         self.maxSizeMB = maxSizeMB
         self.startSize = size
+
+        self.minResizeSize = None
+        self.resizable = True
 	
         if not percent and not size and not preexist:
             raise RuntimeError, "Error with Volume Group:Logical Volume %s:%s - Logical Volume must specify either percentage of vgsize or size" % (volgroup, lvname)
 
 	if percent and grow:
             raise RuntimeError, "Error with Volume Group:Logical Volume %s:%s - Logical Volume cannot grow if percentage given" % (volgroup, lvname)
-	    
 
     def __str__(self):
         if self.fstype:
@@ -955,14 +958,19 @@ class LogicalVolumeRequestSpec(RequestSpec):
                                              existing = self.preexist)
         return self.dev
 
-    def getActualSize(self, partitions, diskset):
+    def getActualSize(self, partitions = None, diskset = None, target = False):
         """Return the actual size allocated for the request in megabytes."""
         if self.percent:
+            if partitions is None or diskset is None:
+                raise RuntimeError, "trying to get a percentage lv size on resize path"
             vgreq = partitions.getRequestByID(self.volumeGroup)
 	    vgsize = vgreq.getActualSize(partitions, diskset)
 	    lvsize = int(self.percent * 0.01 * vgsize)
 	    #lvsize = lvm.clampLVSizeRequest(lvsize, vgreq.pesize)
             return lvsize
+        # FIXME: the target bit here is a bit of a hack...
+        elif self.targetSize is not None and target:
+            return self.targetSize
         else:
             return self.size
 
@@ -996,3 +1004,14 @@ class LogicalVolumeRequestSpec(RequestSpec):
                              "containing encrypted physical volumes.")
 
         return RequestSpec.sanityCheckRequest(self, partitions, skipMntPtExistCheck)
+
+    def getMaximumResizeMB(self, partitions):
+        vg = partitions.getRequestByID(self.volumeGroup)
+        print "max is", self.getActualSize(), vg.free, self.getActualSize() + vg.free
+        return self.getActualSize() + vg.free
+
+    def getMinimumResizeMB(self, partitions):
+        if self.minResizeSize is None:
+            log.warning("don't know the minimum size of %s" %(self.logicalVolumeName,))
+            return 1
+        return self.minResizeSize
diff --git a/partitions.py b/partitions.py
index 25871a7..b19b4e3 100644
--- a/partitions.py
+++ b/partitions.py
@@ -278,7 +278,7 @@ class Partitions:
         lvm.vgactivate()
 
         pvs = lvm.pvlist()
-        for (vg, size, pesize) in lvm.vglist():
+        for (vg, size, pesize, vgfree) in lvm.vglist():
             try:
                 preexist_size = float(size)
             except:
@@ -301,6 +301,7 @@ class Partitions:
                                                        pesize = pesize,
                                                        preexist = 1,
                                                        preexist_size = preexist_size)
+            spec.free = vgfree
             vgid = self.addRequest(spec)
 
             for (lvvg, lv, size, lvorigin) in lvm.lvlist():
@@ -332,6 +333,8 @@ class Partitions:
                     format = format, size = lvsize, volgroup = vgid,
                     lvname = lv, mountpoint = mnt, fslabel = fslabel,
                     preexist = 1)
+                if fsystem.isResizable():
+                    spec.minResizeSize = fsystem.getMinimumSize("%s/%s" %(vg, lv))
                 self.addRequest(spec)
 
         for vg in lvm.partialvgs():
@@ -1460,6 +1463,24 @@ class Partitions:
         lvm.vgdeactivate()
         diskset.stopMdRaid()
 
+    def doMetaResizes(self, diskset):
+        """Does resizing of non-physical volumes."""
+        # NOTE: this should be called with volumes active
+
+        # we only support resizing LVM of these types of things currently
+        for lv in self.getLVMLVRequests():
+            if not lv.preexist:
+                continue
+            if lv.targetSize is None:
+                continue
+
+            vg = self.getRequestByID(lv.volumeGroup)
+            if vg is None:
+                continue
+
+            lvm.lvresize(lv.logicalVolumeName, vg.volumeGroupName,
+                         lv.targetSize)
+
     def deleteDependentRequests(self, request):
         """Handle deletion of this request and all requests which depend on it.
 
-- 
1.5.3.4


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