From 1005d81616db39e3a50d360d313dbdacba0abf50 Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Mon, 16 Jun 2008 16:01:03 +0000
Subject: [PATCH] bdev: implement disk resize for lvm/drbd8

This patch implements disk resize at the bdev level for the LVM and
DRBD8 disk types. It is not implemented for DRBD7 and MD since the way
MD works with its underlaying devices makes it harder and this
combination is also deprecated.

The LVM resize operation is tried three times, with different allocation
policies:
  - contiguous first, since this is best for allocation purposes (it
    won't fragment too much the PV)
  - cling, which is supported only by more recent LVM versions, will try
    to place the new extents on the same PV as the rest of the LV
  - and finally normal, which is the default

Reviewed-by: imsnah
---
 lib/bdev.py | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/lib/bdev.py b/lib/bdev.py
index d73d63fee..a3913d4f2 100644
--- a/lib/bdev.py
+++ b/lib/bdev.py
@@ -255,6 +255,16 @@ class BlockDev(object):
     for child in self._children:
       child.SetInfo(text)
 
+  def Grow(self, amount):
+    """Grow the block device.
+
+    Arguments:
+      amount: the amount (in mebibytes) to grow with
+
+    Returns: None
+
+    """
+    raise NotImplementedError
 
   def __repr__(self):
     return ("<%s: unique_id: %s, children: %s, %s:%s, %s>" %
@@ -518,6 +528,21 @@ class LogicalVolume(BlockDev):
       raise errors.BlockDeviceError("Command: %s error: %s - %s" %
                                     (result.cmd, result.fail_reason,
                                      result.output))
+  def Grow(self, amount):
+    """Grow the logical volume.
+
+    """
+    # we try multiple algorithms since the 'best' ones might not have
+    # space available in the right place, but later ones might (since
+    # they have less constraints); also note that only recent LVM
+    # supports 'cling'
+    for alloc_policy in "contiguous", "cling", "normal":
+      result = utils.RunCmd(["lvextend", "--alloc", alloc_policy,
+                             "-L", "+%dm" % amount, self.dev_path])
+      if not result.failed:
+        return
+    raise errors.BlockDeviceError("Can't grow LV %s: %s" %
+                                  (self.dev_path, result.output))
 
 
 class BaseDRBD(BlockDev):
@@ -1330,6 +1355,21 @@ class DRBD8(BaseDRBD):
       raise errors.BlockDeviceError("Cannot initalize meta device")
     return cls(unique_id, children)
 
+  def Grow(self, amount):
+    """Resize the DRBD device and its backing storage.
+
+    """
+    if self.minor is None:
+      raise errors.ProgrammerError("drbd8: Grow called while not attached")
+    if len(self._children) != 2 or None in self._children:
+      raise errors.BlockDeviceError("Cannot grow diskless DRBD8 device")
+    self._children[0].Grow(amount)
+    result = utils.RunCmd(["drbdsetup", self.dev_path, "resize"])
+    if result.failed:
+      raise errors.BlockDeviceError("resize failed for %s: %s" %
+                                    (self.dev_path, result.output))
+    return
+
 
 class FileStorage(BlockDev):
   """File device.
-- 
GitLab