From 878e81d407bf6507ad2f98edcaa84c9835e58f02 Mon Sep 17 00:00:00 2001
From: David Lehman <dlehman@redhat.com>
Date: Thu, 28 Feb 2013 08:52:28 -0600
Subject: [PATCH 15/21] Crude implementation of lvm-on-md factory.

---
 blivet/devicefactory.py | 57 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 48 insertions(+), 9 deletions(-)

diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py
index f548cc5..5f2d2b6 100644
--- a/blivet/devicefactory.py
+++ b/blivet/devicefactory.py
@@ -205,6 +205,30 @@ class DeviceFactory(object):
             container = device
 
         ##
+        ## Handle lvm-on-md.
+        ##
+        if getattr(self, "lvm_on_md"):
+            # XXX I'm not sure if self.container_name is always set here or not.
+            pv_name = ""
+            if self.container_name:
+                pv_name += "%s-" % self.container_name
+
+            pv_name += "pv"
+            pv_device = None
+            md_size = self.device_size
+            if container:
+                # get a proper container size estimate and pass any existing
+                # member device into configure_device
+                md_size = self.container_size_func(container, device)
+                pv_device = container.parents[0]    # XXX single pv, right?
+
+            md_factory = MDFactory(storage, md_size, self.raid_level,
+                                   self.disks, self.encrypted)
+            member = md_factory.configure_device(name=pv_name,
+                                                 device=pv_device)
+            return [member]
+
+        ##
         ## Determine the target disk set.
         ##
 
@@ -586,6 +610,8 @@ class DeviceFactory(object):
                     raise ErrorRecoveryFailure("failed to revert device size")
 
                 raise(e)
+
+            ret = device
         elif self.new_device_attr:
             log.debug("creating new device")
             if self.encrypted and self.encrypt_leaves:
@@ -648,6 +674,7 @@ class DeviceFactory(object):
                 _container_post_error()
                 raise StorageError(e)
 
+            ret = device
             if self.encrypted and self.encrypt_leaves:
                 fmt = getFormat(luks_fmt_type,
                                 mountpoint=luks_mountpoint,
@@ -655,7 +682,9 @@ class DeviceFactory(object):
                 luks_device = LUKSDevice("luks-" + device.name,
                                          parents=[device], format=fmt)
                 self.storage.createDevice(luks_device)
+                ret = luks_device
 
+        return ret
 
 class DiskFactory(DeviceFactory):
     type_desc = "disk"
@@ -765,8 +794,8 @@ class LVMFactory(DeviceFactory):
     new_container_attr = "newVG"
     new_device_attr = "newLV"
     container_list_attr = "vgs"
-    encrypt_members = True
-    encrypt_leaves = False
+    encrypt_members = True      # this should be settable per-instance
+    encrypt_leaves = False      # this should be settable per-instance
 
     def handle_no_size(self, device=None, container=None):
         """ Set device size so that it grows to the largest size possible. """
@@ -783,20 +812,27 @@ class LVMFactory(DeviceFactory):
                                                    container=container)
 
     @property
+    def size_func_kwargs(self):
+        kwargs = {}
+        if not getattr(self, "lvm_on_md"):
+            if self.raid_level in ("raid1", "raid10"):
+                kwargs["mirrored"] = True
+            if self.raid_level in ("raid0", "raid10"):
+                kwargs["striped"] = True
+
+        return kwargs
+
+    @property
     def device_size(self):
-        size_func_kwargs = {}
-        if self.raid_level in ("raid1", "raid10"):
-            size_func_kwargs["mirrored"] = True
-        if self.raid_level in ("raid0", "raid10"):
-            size_func_kwargs["striped"] = True
-        return get_pv_space(self.size, len(self.disks), **size_func_kwargs)
+        return get_pv_space(self.size, len(self.disks), **self.size_func_kwargs)
 
     def container_size_func(self, container, device=None):
         size = sum([p.size for p in container.parents])
         size -= container.freeSpace
         size += self.device_size
         if device:
-            size -= get_pv_space(device.size, len(container.parents))
+            size -= get_pv_space(device.size, len(container.parents),
+                                 **self.size_func_kwargs)
 
         return size
 
@@ -825,6 +861,9 @@ class LVMFactory(DeviceFactory):
 
         return size
 
+class LVMOnMDFactory(LVMFactory):
+    lvm_on_md = True
+
 class MDFactory(DeviceFactory):
     type_desc = "md"
     member_format = "mdmember"
-- 
1.8.1

