From 7f43edf68d62e2b9e31420aa2d8eb132f6af8020 Mon Sep 17 00:00:00 2001
From: Pierre Riteau <pierre@stackhpc.com>
Date: Tue, 26 Mar 2019 15:16:20 +0000
Subject: [PATCH] Add support for configuring software RAID arrays using mdadm

Change-Id: I647d93bf40d42a1b86b06170c8b4cc96972051c4
Story: 2005017
Task: 29495
---
 ansible/group_vars/all/compute                |  6 +++
 ansible/group_vars/all/controllers            |  6 +++
 ansible/group_vars/all/monitoring             |  6 +++
 ansible/group_vars/all/seed                   |  6 +++
 ansible/group_vars/all/seed-hypervisor        |  6 +++
 ansible/group_vars/all/storage                |  6 +++
 ansible/group_vars/compute/mdadm              |  6 +++
 ansible/group_vars/controllers/mdadm          |  6 +++
 ansible/group_vars/monitoring/mdadm           |  9 +++++
 ansible/group_vars/seed-hypervisor/mdadm      |  6 +++
 ansible/group_vars/seed/mdadm                 |  6 +++
 ansible/group_vars/storage/mdadm              |  6 +++
 ansible/mdadm.yml                             | 11 ++++++
 doc/source/configuration/hosts.rst            | 37 +++++++++++++++++++
 etc/kayobe/compute.yml                        |  6 +++
 etc/kayobe/controllers.yml                    |  6 +++
 etc/kayobe/monitoring.yml                     |  6 +++
 etc/kayobe/seed-hypervisor.yml                |  6 +++
 etc/kayobe/seed.yml                           |  6 +++
 etc/kayobe/storage.yml                        |  6 +++
 kayobe/cli/commands.py                        | 13 +++++--
 kayobe/tests/unit/cli/test_commands.py        |  3 ++
 .../notes/mdadm-ed1d301ad0168e91.yaml         |  7 ++++
 requirements.yml                              |  3 ++
 24 files changed, 181 insertions(+), 4 deletions(-)
 create mode 100644 ansible/group_vars/compute/mdadm
 create mode 100644 ansible/group_vars/controllers/mdadm
 create mode 100644 ansible/group_vars/monitoring/mdadm
 create mode 100644 ansible/group_vars/seed-hypervisor/mdadm
 create mode 100644 ansible/group_vars/seed/mdadm
 create mode 100644 ansible/group_vars/storage/mdadm
 create mode 100644 ansible/mdadm.yml
 create mode 100644 releasenotes/notes/mdadm-ed1d301ad0168e91.yaml

diff --git a/ansible/group_vars/all/compute b/ansible/group_vars/all/compute
index 273aabc46..9e5a35491 100644
--- a/ansible/group_vars/all/compute
+++ b/ansible/group_vars/all/compute
@@ -55,6 +55,12 @@ compute_raid_config_default: []
 # stackhpc.drac role.
 compute_raid_config_extra: []
 
+###############################################################################
+# Compute node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+compute_mdadm_arrays: []
+
 ###############################################################################
 # Compute node LVM configuration.
 
diff --git a/ansible/group_vars/all/controllers b/ansible/group_vars/all/controllers
index 96137b045..b265667c1 100644
--- a/ansible/group_vars/all/controllers
+++ b/ansible/group_vars/all/controllers
@@ -66,6 +66,12 @@ controller_raid_config_default: []
 # stackhpc.drac role.
 controller_raid_config_extra: []
 
+###############################################################################
+# Controller node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+controller_mdadm_arrays: []
+
 ###############################################################################
 # Controller node LVM configuration.
 
diff --git a/ansible/group_vars/all/monitoring b/ansible/group_vars/all/monitoring
index 4174b2525..b89bd340c 100644
--- a/ansible/group_vars/all/monitoring
+++ b/ansible/group_vars/all/monitoring
@@ -55,6 +55,12 @@ monitoring_raid_config_default: "{{ controller_raid_config_default }}"
 # by stackhpc.drac role.
 monitoring_raid_config_extra: "{{ controller_raid_config_extra }}"
 
+###############################################################################
+# Monitoring node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+monitoring_mdadm_arrays: []
+
 ###############################################################################
 # Monitoring node LVM configuration.
 
diff --git a/ansible/group_vars/all/seed b/ansible/group_vars/all/seed
index ab10dd71c..12620ae79 100644
--- a/ansible/group_vars/all/seed
+++ b/ansible/group_vars/all/seed
@@ -23,6 +23,12 @@ seed_default_network_interfaces: >
 # List of extra networks to which seed nodes are attached.
 seed_extra_network_interfaces: []
 
+###############################################################################
+# Seed node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+seed_mdadm_arrays: []
+
 ###############################################################################
 # Seed node LVM configuration.
 
diff --git a/ansible/group_vars/all/seed-hypervisor b/ansible/group_vars/all/seed-hypervisor
index 8af56b02a..506b4dbfe 100644
--- a/ansible/group_vars/all/seed-hypervisor
+++ b/ansible/group_vars/all/seed-hypervisor
@@ -20,6 +20,12 @@ seed_hypervisor_default_network_interfaces: "{{ seed_default_network_interfaces
 # List of extra networks to which seed hypervisor nodes are attached.
 seed_hypervisor_extra_network_interfaces: "{{ seed_extra_network_interfaces }}"
 
+###############################################################################
+# Seed hypervisor node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+seed_hypervisor_mdadm_arrays: []
+
 ###############################################################################
 # Seed hypervisor node LVM configuration.
 
diff --git a/ansible/group_vars/all/storage b/ansible/group_vars/all/storage
index c1dce7668..45531dffc 100644
--- a/ansible/group_vars/all/storage
+++ b/ansible/group_vars/all/storage
@@ -54,6 +54,12 @@ storage_raid_config_default: []
 # stackhpc.drac role.
 storage_raid_config_extra: []
 
+###############################################################################
+# Storage node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+storage_mdadm_arrays: []
+
 ###############################################################################
 # Storage node LVM configuration.
 
diff --git a/ansible/group_vars/compute/mdadm b/ansible/group_vars/compute/mdadm
new file mode 100644
index 000000000..101132505
--- /dev/null
+++ b/ansible/group_vars/compute/mdadm
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Compute node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+mdadm_arrays: "{{ compute_mdadm_arrays }}"
diff --git a/ansible/group_vars/controllers/mdadm b/ansible/group_vars/controllers/mdadm
new file mode 100644
index 000000000..aaf13c044
--- /dev/null
+++ b/ansible/group_vars/controllers/mdadm
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Controller node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+mdadm_arrays: "{{ controller_mdadm_arrays }}"
diff --git a/ansible/group_vars/monitoring/mdadm b/ansible/group_vars/monitoring/mdadm
new file mode 100644
index 000000000..68627f8ca
--- /dev/null
+++ b/ansible/group_vars/monitoring/mdadm
@@ -0,0 +1,9 @@
+---
+###############################################################################
+# Monitoring node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+mdadm_arrays: >
+  {{ controller_mdadm_arrays
+     if inventory_hostname in groups['controllers'] else
+     monitoring_mdadm_arrays }}
diff --git a/ansible/group_vars/seed-hypervisor/mdadm b/ansible/group_vars/seed-hypervisor/mdadm
new file mode 100644
index 000000000..f706f3df6
--- /dev/null
+++ b/ansible/group_vars/seed-hypervisor/mdadm
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Seed hypervisor node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+mdadm_arrays: "{{ seed_hypervisor_mdadm_arrays }}"
diff --git a/ansible/group_vars/seed/mdadm b/ansible/group_vars/seed/mdadm
new file mode 100644
index 000000000..cc321f97a
--- /dev/null
+++ b/ansible/group_vars/seed/mdadm
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Seed node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+mdadm_arrays: "{{ seed_mdadm_arrays }}"
diff --git a/ansible/group_vars/storage/mdadm b/ansible/group_vars/storage/mdadm
new file mode 100644
index 000000000..a7b82021b
--- /dev/null
+++ b/ansible/group_vars/storage/mdadm
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Storage node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+mdadm_arrays: "{{ storage_mdadm_arrays }}"
diff --git a/ansible/mdadm.yml b/ansible/mdadm.yml
new file mode 100644
index 000000000..617b65e47
--- /dev/null
+++ b/ansible/mdadm.yml
@@ -0,0 +1,11 @@
+---
+- name: Ensure software RAID configuration is applied
+  hosts: seed-hypervisor:seed:overcloud
+  tags:
+    - mdadm
+  roles:
+    - name: mrlesmithjr.mdadm
+      become: True
+      when:
+        - mdadm_arrays is defined
+        - mdadm_arrays | length > 0
diff --git a/doc/source/configuration/hosts.rst b/doc/source/configuration/hosts.rst
index be105cf1f..2916f62a9 100644
--- a/doc/source/configuration/hosts.rst
+++ b/doc/source/configuration/hosts.rst
@@ -359,6 +359,43 @@ The NTP service may be disabled as follows:
    ntp_service_state: stopped
    ntp_service_enabled: false
 
+.. _configuration-hosts-mdadm:
+
+Software RAID
+=============
+
+While it is possible to use RAID directly with LVM, some operators may prefer
+the userspace tools provided by ``mdadm`` or may have existing software RAID
+arrays they want to manage with Kayobe.
+
+Software RAID arrays may be configured via the ``mdadm_arrays`` variable. For
+convenience, this is mapped to the following variables:
+
+* ``seed_hypervisor_mdadm_arrays``
+* ``seed_mdadm_arrays``
+* ``compute_mdadm_arrays``
+* ``controller_mdadm_arrays``
+* ``monitoring_mdadm_arrays``
+* ``storage_mdadm_arrays``
+
+The format of these variables is as defined by the ``mdadm_arrays`` variable of
+the `mrlesmithjr.mdadm <https://galaxy.ansible.com/mrlesmithjr/mdadm>`__
+Ansible role.
+
+For example, to configure two of the seed's disks as a RAID1 ``mdadm`` array
+available as ``/dev/md0``:
+
+.. code-block:: yaml
+   :caption: ``seed.yml``
+
+   seed_mdadm_arrays:
+     - name: md0
+       devices:
+         - /dev/sdb
+         - /dev/sdc
+       level: '1'
+       state: present
+
 .. _configuration-hosts-lvm:
 
 LVM
diff --git a/etc/kayobe/compute.yml b/etc/kayobe/compute.yml
index 8d97cec16..d66c4d56b 100644
--- a/etc/kayobe/compute.yml
+++ b/etc/kayobe/compute.yml
@@ -48,6 +48,12 @@
 # stackhpc.drac role.
 #compute_raid_config_extra:
 
+###############################################################################
+# Compute node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+#compute_mdadm_arrays:
+
 ###############################################################################
 # Compute node LVM configuration.
 
diff --git a/etc/kayobe/controllers.yml b/etc/kayobe/controllers.yml
index 0af11ebdc..3b617b777 100644
--- a/etc/kayobe/controllers.yml
+++ b/etc/kayobe/controllers.yml
@@ -51,6 +51,12 @@
 # stackhpc.drac role.
 #controller_raid_config_extra:
 
+###############################################################################
+# Controller node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+#controller_mdadm_arrays:
+
 ###############################################################################
 # Controller node LVM configuration.
 
diff --git a/etc/kayobe/monitoring.yml b/etc/kayobe/monitoring.yml
index 0b64855c8..30690a2fe 100644
--- a/etc/kayobe/monitoring.yml
+++ b/etc/kayobe/monitoring.yml
@@ -48,6 +48,12 @@
 # by stackhpc.drac role.
 #monitoring_raid_config_extra:
 
+###############################################################################
+# Monitoring node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+#monitoring_mdadm_arrays:
+
 ###############################################################################
 # Monitoring node LVM configuration.
 
diff --git a/etc/kayobe/seed-hypervisor.yml b/etc/kayobe/seed-hypervisor.yml
index 978a98cc5..8f928a717 100644
--- a/etc/kayobe/seed-hypervisor.yml
+++ b/etc/kayobe/seed-hypervisor.yml
@@ -18,6 +18,12 @@
 # List of extra networks to which seed hypervisor nodes are attached.
 #seed_hypervisor_extra_network_interfaces:
 
+###############################################################################
+# Seed hypervisor node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+#seed_hypervisor_mdadm_arrays:
+
 ###############################################################################
 # Seed hypervisor node LVM configuration.
 
diff --git a/etc/kayobe/seed.yml b/etc/kayobe/seed.yml
index c3d92763c..a1c5b1a1d 100644
--- a/etc/kayobe/seed.yml
+++ b/etc/kayobe/seed.yml
@@ -18,6 +18,12 @@
 # List of extra networks to which seed nodes are attached.
 #seed_extra_network_interfaces:
 
+###############################################################################
+# Seed node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+#seed_mdadm_arrays:
+
 ###############################################################################
 # LVM configuration.
 
diff --git a/etc/kayobe/storage.yml b/etc/kayobe/storage.yml
index e1e1795cc..8de2051f6 100644
--- a/etc/kayobe/storage.yml
+++ b/etc/kayobe/storage.yml
@@ -48,6 +48,12 @@
 # stackhpc.drac role.
 #storage_raid_config_extra:
 
+###############################################################################
+# Storage node software RAID configuration.
+
+# List of software RAID arrays. See mrlesmithjr.mdadm role for format.
+#storage_mdadm_arrays:
+
 ###############################################################################
 # Storage node LVM configuration.
 
diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py
index ea4cf5d19..9a9c70c33 100644
--- a/kayobe/cli/commands.py
+++ b/kayobe/cli/commands.py
@@ -290,6 +290,7 @@ class SeedHypervisorHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin,
     * Configure the host's network interfaces.
     * Set sysctl parameters.
     * Configure NTP.
+    * Optionally, configure software RAID arrays.
     * Configure LVM volumes.
     * Configure the host as a libvirt hypervisor.
     """
@@ -326,8 +327,8 @@ class SeedHypervisorHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin,
         if parsed_args.wipe_disks:
             playbooks += _build_playbook_list("wipe-disks")
         playbooks += _build_playbook_list(
-            "users", "yum", "dev-tools", "network", "sysctl", "ntp", "lvm",
-            "seed-hypervisor-libvirt-host")
+            "users", "yum", "dev-tools", "network", "sysctl", "ntp", "mdadm",
+            "lvm", "seed-hypervisor-libvirt-host")
         self.run_kayobe_playbooks(parsed_args, playbooks,
                                   limit="seed-hypervisor")
 
@@ -421,6 +422,7 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
     * Configure IP routing and source NAT.
     * Disable bootstrap interface configuration.
     * Configure NTP.
+    * Optionally, configure software RAID arrays.
     * Configure LVM volumes.
     * Optionally, create a virtualenv for kolla-ansible.
     * Configure a user account for kolla-ansible.
@@ -469,7 +471,8 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
             playbooks += _build_playbook_list("wipe-disks")
         playbooks += _build_playbook_list(
             "users", "yum", "dev-tools", "disable-selinux", "network",
-            "sysctl", "ip-routing", "snat", "disable-glean", "ntp", "lvm")
+            "sysctl", "ip-routing", "snat", "disable-glean", "ntp", "mdadm",
+            "lvm")
         self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed")
         playbooks = _build_playbook_list("kolla-ansible")
         self.run_kayobe_playbooks(parsed_args, playbooks, tags="config")
@@ -823,6 +826,7 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
     * Set sysctl parameters.
     * Disable bootstrap interface configuration.
     * Configure NTP.
+    * Optionally, configure software RAID arrays.
     * Configure LVM volumes.
     * Optionally, create a virtualenv for kolla-ansible.
     * Configure a user account for kolla-ansible.
@@ -870,7 +874,8 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
             playbooks += _build_playbook_list("wipe-disks")
         playbooks += _build_playbook_list(
             "users", "yum", "dev-tools", "disable-selinux", "network",
-            "sysctl", "disable-glean", "disable-cloud-init", "ntp", "lvm")
+            "sysctl", "disable-glean", "disable-cloud-init", "ntp", "mdadm",
+            "lvm")
         self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud")
         playbooks = _build_playbook_list("kolla-ansible")
         self.run_kayobe_playbooks(parsed_args, playbooks, tags="config")
diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py
index e4e23fef9..14a9527d1 100644
--- a/kayobe/tests/unit/cli/test_commands.py
+++ b/kayobe/tests/unit/cli/test_commands.py
@@ -268,6 +268,7 @@ class TestCase(unittest.TestCase):
                     utils.get_data_files_path("ansible", "network.yml"),
                     utils.get_data_files_path("ansible", "sysctl.yml"),
                     utils.get_data_files_path("ansible", "ntp.yml"),
+                    utils.get_data_files_path("ansible", "mdadm.yml"),
                     utils.get_data_files_path("ansible", "lvm.yml"),
                     utils.get_data_files_path(
                         "ansible", "seed-hypervisor-libvirt-host.yml"),
@@ -373,6 +374,7 @@ class TestCase(unittest.TestCase):
                     utils.get_data_files_path("ansible", "snat.yml"),
                     utils.get_data_files_path("ansible", "disable-glean.yml"),
                     utils.get_data_files_path("ansible", "ntp.yml"),
+                    utils.get_data_files_path("ansible", "mdadm.yml"),
                     utils.get_data_files_path("ansible", "lvm.yml"),
                 ],
                 limit="seed",
@@ -982,6 +984,7 @@ class TestCase(unittest.TestCase):
                     utils.get_data_files_path(
                         "ansible", "disable-cloud-init.yml"),
                     utils.get_data_files_path("ansible", "ntp.yml"),
+                    utils.get_data_files_path("ansible", "mdadm.yml"),
                     utils.get_data_files_path("ansible", "lvm.yml"),
                 ],
                 limit="overcloud",
diff --git a/releasenotes/notes/mdadm-ed1d301ad0168e91.yaml b/releasenotes/notes/mdadm-ed1d301ad0168e91.yaml
new file mode 100644
index 000000000..256220d83
--- /dev/null
+++ b/releasenotes/notes/mdadm-ed1d301ad0168e91.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    Adds support for configuring software RAID arrays using ``mdadm``. Software
+    RAID configuration is applied before LVM configuration, which allows
+    creating LVM volumes on top of software RAID arrays. See `story 2005017
+    <https://storyboard.openstack.org/#!/story/2005017>`__ for details.
diff --git a/requirements.yml b/requirements.yml
index 884e0a6fc..87202993e 100644
--- a/requirements.yml
+++ b/requirements.yml
@@ -8,6 +8,9 @@
   version: v1.2.0
 - src: mrlesmithjr.manage-lvm
   version: v0.1.4
+- src: mrlesmithjr.mdadm
+  # There are no versioned releases of this role.
+  version: 5be3ee7d330aa17317897bd104dc87ff0df11915
 - src: resmo.ntp
   version: 0.4.0
 - src: singleplatform-eng.users