summaryrefslogtreecommitdiffstats
path: root/ansible_collections/dellemc/powerflex/roles
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
commit7fec0b69a082aaeec72fee0612766aa42f6b1b4d (patch)
treeefb569b86ca4da888717f5433e757145fa322e08 /ansible_collections/dellemc/powerflex/roles
parentReleasing progress-linux version 7.7.0+dfsg-3~progress7.99u1. (diff)
downloadansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.tar.xz
ansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.zip
Merging upstream version 9.4.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/dellemc/powerflex/roles')
-rw-r--r--ansible_collections/dellemc/powerflex/roles/README.md117
-rw-r--r--ansible_collections/dellemc/powerflex/roles/molecule.yml25
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/README.md155
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/defaults/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/argument_specs.yml48
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/main.yml27
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/converge.yml31
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/converge.yml67
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/install_activemq.yml30
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/uninstall_activemq.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_activemq/vars/main.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/README.md3
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/defaults/main.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/meta/main.yml41
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_CentOS.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_RedHat.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Rocky.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_SLES.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Ubuntu.yml10
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_CentOS.yml36
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_RedHat.yml36
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Rocky.yml36
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_SLES.yml36
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Ubuntu.yml51
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_VMkernel.yml50
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_WindowsOS.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_powerflex.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/main.yml14
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/CentOS.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/RedHat.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Rocky.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/SLES.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Ubuntu.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/VMkernel.yml2
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/WindowsOS.yml2
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/README.md165
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/defaults/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/argument_specs.yml50
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/main.yml25
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/converge.yml47
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/tasks/main.yml79
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_config/vars/main.yml2
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/README.md160
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/defaults/main.yml17
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/handlers/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/argument_specs.yml47
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/main.yml28
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/converge.yml29
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/converge.yml32
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/molecule.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/converge.yml48
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_gateway.yml52
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_keepalived.yml28
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/uninstall_gateway.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/templates/keepalived.conf.j218
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/CentOS.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/RedHat.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/SLES.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/Ubuntu.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/README.md170
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/defaults/main.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/meta/main.yml27
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/converge.yml30
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/converge.yml34
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/molecule.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/converge.yml30
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/install_lia.yml22
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/uninstall_lia.yml19
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_lia/vars/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/README.md142
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/defaults/main.yml9
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/argument_spec.yml28
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/main.yml29
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/converge.yml63
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/converge.yml53
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/add_certs.yml168
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_mdm.yml32
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex3x_mdm.yml128
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex4x_mdm.yml101
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/mdm_set_facts.yml40
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/remove_mdm.yml58
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/uninstall_mdm.yml19
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/CentOS.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/RedHat.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/SLES.yml3
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/Ubuntu.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/README.md311
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/defaults/main.yml21
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/handlers/main.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/meta/main.yml25
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/converge.yml118
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/molecule.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/converge.yml62
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/converge.yml54
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/molecule.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/converge.yml57
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/var_values.yml7
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/converge.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/inventory4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/molecule.yml11
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/converge.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/inventory4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/molecule.yml11
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/configure_sdc.yml28
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/install_sdc.yml75
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/register_esxi_sdc.yml47
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/remove_sdc.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_esxi_sdc.yml30
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_sdc.yml40
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/templates/driver_sync.conf.j231
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdc/vars/main.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/README.md145
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/defaults/main.yml9
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/argument_specs.yml34
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/main.yml21
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/converge.yml30
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/converge.yml34
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/molecule.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/converge.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/molecule.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/converge.yml66
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/var_values.yml3
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/add_sdr.yml142
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/remove_sdr.yml120
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/sdr_set_facts.yml7
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sdr/vars/main.yml2
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/README.md243
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/defaults/main.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/argument_spec.yml88
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/main.yml24
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/converge.yml55
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/converge.yml50
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/var_values.yml11
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/install_sds.yml112
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/uninstall_sds.yml31
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_sds/vars/main.yml5
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/README.md210
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/defaults/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_spec.yml85
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_specs.yml65
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/main.yml25
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/converge.yml35
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/converge.yml19
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/var_values.yml7
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/converge.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/inventory4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/molecule.yml11
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb3x.yml81
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb4x.yml69
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/main.yml31
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/set_tb_ips.yml29
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/uninstall_tb.yml97
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_tb/vars/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/README.md165
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/defaults/main.yml6
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/argument_specs.yml52
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/main.yml29
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/converge.yml30
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/converge.yml34
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/molecule.yml4
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/converge.yml48
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/molecule.yml1
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/install_webui.yml23
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/main.yml8
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/uninstall_webui.yml20
-rw-r--r--ansible_collections/dellemc/powerflex/roles/powerflex_webui/vars/main.yml5
194 files changed, 6633 insertions, 0 deletions
diff --git a/ansible_collections/dellemc/powerflex/roles/README.md b/ansible_collections/dellemc/powerflex/roles/README.md
new file mode 100644
index 000000000..e6f8c426a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/README.md
@@ -0,0 +1,117 @@
+## Supported Roles
+
+#dellemc.powerflex roles directory
+
+Here is the list of supported roles.
+
+```
+.
+├── powerflex_common
+├── powerflex_mdm
+├── powerflex_gateway
+├── powerflex_sdc
+├── powerflex_sdr
+├── powerflex_lia
+├── powerflex_tb
+├── powerflex_sds
+├── powerflex_config
+├── powerflex_activeMQ
+
+```
+
+## Role Descriptions
+
+Below is the brief description of each role
+
+<table>
+<thead>
+ <tr>
+ <th>Role Name</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>powerflex_common</td>
+ <td>Role to manage the common operations of Powerflex.</td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway</td>
+ <td>Role to manage the installation and uninstallation of Powerflex Gateway.</td>
+ </tr>
+ <tr>
+ <td>powerflex_lia</td>
+ <td>Role to manage the installation and uninstallation of Powerflex LIA.</td>
+ </tr>
+ <tr>
+ <td>powerflex_mdm</td>
+ <td>Role to manage the installation and uninstallation of Powerflex MDM.</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc</td>
+ <td>Role to manage the installation and uninstallation of Powerflex SDC.</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdr</td>
+ <td>Role to manage installation and uninstallation PowerFlex SDR.</td>
+ </tr>
+ <tr>
+ <td>powerflex_sds</td>
+ <td>Role to manage the installation and uninstallation of Powerflex SDS.</td>
+ </tr>
+ <tr>
+ <td>powerflex_tb</td>
+ <td>Role to manage the installation and uninstallation of Powerflex TB.</td>
+ </tr>
+ <tr>
+ <td>powerflex_webui</td>
+ <td>Role to manage the installation and uninstallation of Powerflex Web UI.</td>
+ </tr>
+ <tr>
+ <td>powerflex_config</td>
+ <td>Role to configure the protection domain, fault set and storage pool.</td>
+ </tr>
+ <tr>
+ <td>powerflex_activeMQ</td>
+ <td>Role to manage the installation and uninstallation of Powerflex ActiveMQ.</td>
+ </tr>
+</tbody>
+</table>
+
+## Acronyms and their full forms
+Below is the list of full form of the acronyms which are refered throughout the documentation
+
+<table>
+<thead>
+ <tr>
+ <th>Acronym</th>
+ <th>Full Form</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>LIA</td>
+ <td>Lightweight Installation Agent.</td>
+ </tr>
+ <tr>
+ <td>MDM</td>
+ <td>Metadata Manager.</td>
+ </tr>
+ <tr>
+ <td>SDC</td>
+ <td>Storage Data Client.</td>
+ </tr>
+ <tr>
+ <td>SDR</td>
+ <td>Storage Data Replicator.</td>
+ </tr>
+ <tr>
+ <td>SDS</td>
+ <td>Storage Data Server.</td>
+ </tr>
+ <tr>
+ <td>TB</td>
+ <td>Tie Breaker.</td>
+ </tr>
+</tbody>
+</table>
diff --git a/ansible_collections/dellemc/powerflex/roles/molecule.yml b/ansible_collections/dellemc/powerflex/roles/molecule.yml
new file mode 100644
index 000000000..425cea9d1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/molecule.yml
@@ -0,0 +1,25 @@
+---
+dependency:
+ name: galaxy
+driver:
+ name: docker
+platforms:
+ - name: centos
+ image: quay.io/centos/centos:stream8
+ pre_build_image: true
+ volumes:
+ - /tmp:/tmp
+provisioner:
+ name: ansible
+ inventory:
+ links:
+ hosts: ../../../../playbooks/roles/inventory
+ group_vars: ../../../../playbooks/roles/group_vars/
+ host_vars: ../../../../playbooks/roles/host_vars/
+verifier:
+ name: ansible
+scenario:
+ test_sequence:
+ - check
+ - converge
+ - idempotence
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/README.md
new file mode 100644
index 000000000..bdaf5efac
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/README.md
@@ -0,0 +1,155 @@
+# powerflex_activemq
+
+Role to manage the installation and uninstallation of Powerflex ActiveMQ.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Notes](#notes)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td>IP or FQDN of the PowerFlex host.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td>The username of the PowerFlex host.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td>The password of the PowerFlex host.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>false</td>
+ <td>The port of the PowerFlex host.</td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>If C(false), the SSL certificates will not be validated.<br>Configure C(false) only on personally controlled sites where self-signed certificates are used.</td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>timeout</td>
+ <td>false</td>
+ <td>Time after which connection will get terminated.</td>
+ <td></td>
+ <td>int</td>
+ <td>120</td>
+ </tr>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>true</td>
+ <td>Location of installation and rpm gpg files to be installed.
+ <br>The required, compatible installation software package based on the operating system of the node. The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>path</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_activemq_state</td>
+ <td>false</td>
+ <td>Specify state of ActiveMQ.
+ <br>present will install the ActiveMQ and absent will uninstall the ActiveMQ.</td>
+ <td>absent, present</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Install and configure PowerFlex ActiveMQ
+ ansible.builtin.import_role:
+ name: powerflex_activemq
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_activemq_state: present
+
+ - name: Uninstall powerflex ActiveMQ
+ ansible.builtin.import_role:
+ name: powerflex_activemq
+ vars:
+ powerflex_activemq_state: absent
+
+```
+## Notes
+- Supported in PowerFlex version 4.x and above
+
+## Usage instructions
+----
+### To install all dependency packages, including ActiveMQ, on node:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+### To uninstall ActiveMQ:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies<br>
+Pavan Mudunuri (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/defaults/main.yml
new file mode 100644
index 000000000..646a6bf28
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/defaults/main.yml
@@ -0,0 +1,6 @@
+---
+file_glob_name: activemq
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_activemq_mdm_ips }}"
+powerflex_activemq_state: 'present'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/argument_specs.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/argument_specs.yml
new file mode 100644
index 000000000..4a793e5e9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/argument_specs.yml
@@ -0,0 +1,48 @@
+---
+argument_specs:
+ main:
+ short_description: Role to manage the installation and uninstallation of Powerflex ActiveMQ.
+ description:
+ - Role to manage the installation and uninstallation of Powerflex ActiveMQ.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: IP or FQDN of the PowerFlex host.
+ username:
+ required: true
+ type: str
+ description: The username of the PowerFlex host.
+ password:
+ required: true
+ type: str
+ description: The password of the PowerFlex host.
+ port:
+ type: int
+ description: Port of the PowerFlex host.
+ default: 443
+ validate_certs:
+ description:
+ - If C(false), the SSL certificates will not be validated.
+ - Configure C(false) only on personally controlled sites where self-signed certificates are used.
+ type: bool
+ default: false
+ timeout:
+ description: Time after which connection will get terminated.
+ type: int
+ default: 120
+ powerflex_common_file_install_location:
+ description:
+ - Location of installation, compatible installation software package
+ based on the operating system of the node.
+ - The files can be downloaded from the Dell Product support page for PowerFlex software.
+ type: path
+ default: /var/tmp
+ powerflex_activemq_state:
+ description:
+ - Specifies the state of the ActiveMQ.
+ - present will install the ActiveMQ if not already installed.
+ - absent will uninstall the ActiveMQ if installed.
+ type: str
+ choices: ['absent', 'present']
+ default: present
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/main.yml
new file mode 100644
index 000000000..7d16f052e
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/meta/main.yml
@@ -0,0 +1,27 @@
+---
+galaxy_info:
+ author: Pavan Mudunuri
+ description: Role to manage the installation and uninstallation of Powerflex ActiveMQ.
+ company: Dell Technologies
+ role_name: powerflex_activemq
+ namespace: dellemc
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.14.0"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/converge.yml
new file mode 100644
index 000000000..be4d31ed7
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/converge.yml
@@ -0,0 +1,31 @@
+---
+- name: Molecule Test for installation of ActiveMQ
+ hosts: activemq
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Install and configure Powerflex ActiveMQ
+ ansible.builtin.import_role:
+ name: powerflex_activemq
+ vars:
+ powerflex_activemq_state: present
+
+ - name: Verifying install package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_install_package_output.msg == "Check mode: No changes made"
+ when: ansible_check_mode
+
+ - name: Verifying installation package in normal mode
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: Verifying installation package in Idempotency mode
+ ansible.builtin.assert:
+ that: >
+ "'Nothing to do' in powerflex_common_install_package_output.results[0]" or
+ "'is already installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and not powerflex_common_install_package_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_install/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/converge.yml
new file mode 100644
index 000000000..3507299d0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/converge.yml
@@ -0,0 +1,67 @@
+---
+- name: Molecule Test for uninstallation of ActiveMQ
+ hosts: activemq
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Uninstall powerflex ActiveMQ
+ ansible.builtin.import_role:
+ name: powerflex_activemq
+ vars:
+ powerflex_activemq_state: absent
+
+ - name: Verifying uninstall package in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Removed:' in powerflex_activemq_uninstall_output.results[0].results[0]"
+ when:
+ - not ansible_check_mode
+ - powerflex_activemq_uninstall_output.changed
+ - ansible_distribution in ("RedHat", "CentOS", "SLES", "Rocky")
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_activemq_uninstall_output.msg == "Check mode: No changes made"
+ when:
+ - ansible_check_mode
+ - ansible_distribution in ("RedHat", "CentOS", "SLES", "Rocky")
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that: >
+ "'Nothing to do' in powerflex_activemq_uninstall_output.results[0].msg" or
+ "'EMC-ScaleIO-activemq is not installed' in powerflex_activemq_uninstall_output.results[0].results[0]"
+ when:
+ - not ansible_check_mode
+ - not powerflex_activemq_uninstall_output.changed
+ - ansible_distribution in ("RedHat", "CentOS", "SLES", "Rocky")
+
+ - name: Verifying uninstall package in check mode for ubuntu
+ ansible.builtin.assert:
+ that:
+ - powerflex_activemq_uninstall_deb_output.results[0].msg == "Check mode: No changes made"
+ - powerflex_activemq_uninstall_deb_output.changed
+ when:
+ - ansible_check_mode
+ - ansible_distribution == "Ubuntu"
+
+ - name: Verifying uninstall package in normal mode for ubuntu
+ ansible.builtin.assert:
+ that:
+ - "'Removed:' in powerflex_activemq_uninstall_deb_output.results[0].results[0]"
+ when:
+ - not ansible_check_mode
+ - powerflex_activemq_uninstall_deb_output.changed
+ - ansible_distribution == "Ubuntu"
+
+ - name: Verifying uninstall package in Idempotency for ubuntu
+ ansible.builtin.assert:
+ that: >
+ "'Nothing to do' in powerflex_activemq_uninstall_deb_output.results[0].msg" or
+ "'is not installed' in powerflex_activemq_uninstall_deb_output.results[0].results[0]"
+ when:
+ - not ansible_check_mode
+ - not powerflex_activemq_uninstall_deb_output.changed
+ - ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/molecule/activemq_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/install_activemq.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/install_activemq.yml
new file mode 100644
index 000000000..8b0dd44d7
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/install_activemq.yml
@@ -0,0 +1,30 @@
+---
+- name: Set facts for MDM counts
+ ansible.builtin.set_fact:
+ mdm_count: "{{ groups['mdm'] | length }}"
+
+- name: Set facts for powerflex_activemq_primary_ip
+ ansible.builtin.set_fact:
+ powerflex_activemq_primary_ip: "{{ hostvars[groups['mdm'][0]]['ansible_host'] }}"
+
+- name: Set facts for powerflex_activemq_secondary_ip
+ ansible.builtin.set_fact:
+ powerflex_activemq_secondary_ip: "{{ hostvars[groups['mdm'][1]]['ansible_host'] }}"
+
+- name: Set facts for powerflex_activemq_tertiary_ip
+ ansible.builtin.set_fact:
+ powerflex_activemq_tertiary_ip: "{{ hostvars[groups['mdm'][2]]['ansible_host'] }}"
+ when: mdm_count | int > 2
+
+- name: Set facts for powerflex_activemq_mdm_ips if mdm_count is 2
+ ansible.builtin.set_fact:
+ powerflex_activemq_mdm_ips: "{{ powerflex_activemq_primary_ip }},{{ powerflex_activemq_secondary_ip }}"
+ when: mdm_count | int == 2
+
+- name: Set facts for powerflex_activemq_mdm_ips if mdm_count is more than 2
+ ansible.builtin.set_fact:
+ powerflex_activemq_mdm_ips: "{{ powerflex_activemq_primary_ip }},{{ powerflex_activemq_secondary_ip }},{{ powerflex_activemq_tertiary_ip }}"
+ when: mdm_count | int > 2
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/main.yml
new file mode 100644
index 000000000..1f3a708b6
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Install ActiveMQ
+ ansible.builtin.include_tasks: install_activemq.yml
+ when: powerflex_activemq_state == 'present'
+
+- name: Uninstall ActiveMQ
+ ansible.builtin.include_tasks: uninstall_activemq.yml
+ when: powerflex_activemq_state == 'absent'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/uninstall_activemq.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/uninstall_activemq.yml
new file mode 100644
index 000000000..1f45e94c0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/tasks/uninstall_activemq.yml
@@ -0,0 +1,20 @@
+---
+- name: Uninstall package
+ register: powerflex_activemq_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-activemq
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES", "Rocky")
+
+- name: Uninstall deb package
+ register: powerflex_activemq_uninstall_deb_output
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - emc-scaleio-activemq
+ when: ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/vars/main.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_activemq/vars/main.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_common/README.md
new file mode 100644
index 000000000..f681f6ac4
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/README.md
@@ -0,0 +1,3 @@
+# powerflex_common
+
+Role to manage the common operations of Powerflex.
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/defaults/main.yml
new file mode 100644
index 000000000..b0ea37ec6
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/defaults/main.yml
@@ -0,0 +1,4 @@
+---
+powerflex_common_file_install_location: "/var/tmp"
+powerflex_common_esxi_files_location: "/tmp/"
+powerflex_common_win_package_location: "C:\\Windows\\Temp"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/meta/main.yml
new file mode 100644
index 000000000..bbe74f9e0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/meta/main.yml
@@ -0,0 +1,41 @@
+---
+galaxy_info:
+ author: Jennifer John
+ description: The role helps to manage the common functions of PowerFlex.
+ company: Dell Technologies
+ role_name: powerflex_common
+ namespace: dellemc
+ # If the issue tracker for your role is not on github, uncomment the
+ # next line and provide a value
+ # issue_tracker_url: http://example.com/issue/tracker
+
+ # Choose a valid license ID from https://spdx.org - some suggested licenses:
+ # - BSD-3-Clause (default)
+ # - MIT
+ # - GPL-2.0-or-later
+ # - GPL-3.0-only
+ # - Apache-2.0
+ # - CC-BY-4.0
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.14.0"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+ # List tags for your role here, one per line. A tag is a keyword that describes
+ # and categorizes the role. Users find roles by searching for tags. Be sure to
+ # remove the '[]' above, if you add tags to this list.
+ #
+ # NOTE: A tag is limited to a single word comprised of alphanumeric characters.
+ # Maximum 20 tags per role.
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_CentOS.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_CentOS.yml
new file mode 100644
index 000000000..33922039b
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_CentOS.yml
@@ -0,0 +1,5 @@
+---
+- name: Install pre-requisite java
+ ansible.builtin.package:
+ name: "java-1.8.0-openjdk-devel"
+ state: "present"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_RedHat.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_RedHat.yml
new file mode 100644
index 000000000..33922039b
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_RedHat.yml
@@ -0,0 +1,5 @@
+---
+- name: Install pre-requisite java
+ ansible.builtin.package:
+ name: "java-1.8.0-openjdk-devel"
+ state: "present"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Rocky.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Rocky.yml
new file mode 100644
index 000000000..33922039b
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Rocky.yml
@@ -0,0 +1,5 @@
+---
+- name: Install pre-requisite java
+ ansible.builtin.package:
+ name: "java-1.8.0-openjdk-devel"
+ state: "present"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_SLES.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_SLES.yml
new file mode 100644
index 000000000..484286982
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_SLES.yml
@@ -0,0 +1,5 @@
+---
+- name: Install pre-requisite java
+ ansible.builtin.package:
+ name: "java-11-openjdk-headless"
+ state: "present"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Ubuntu.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Ubuntu.yml
new file mode 100644
index 000000000..97de45222
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_java_Ubuntu.yml
@@ -0,0 +1,10 @@
+---
+- name: Install pre-requisite binutils
+ ansible.builtin.package:
+ name: "binutils"
+ state: "present"
+
+- name: Install pre-requisite java
+ ansible.builtin.package:
+ name: "openjdk-8-jdk"
+ state: "present"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_CentOS.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_CentOS.yml
new file mode 100644
index 000000000..35d08f875
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_CentOS.yml
@@ -0,0 +1,36 @@
+---
+- name: Copy files
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "/var/tmp/"
+ mode: "0644"
+ register: powerflex_common_file
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*"
+ - "{{ powerflex_common_file_install_location }}/{{ file_gpg_name }}*"
+
+- name: List the rpm file
+ register: powerflex_common_package_file
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "*{{ file_glob_name }}*.rpm"
+
+- name: List the rpm gpg file
+ register: powerflex_common_package_gpg
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "{{ file_gpg_name }}*"
+
+- name: Import gpg key
+ ansible.builtin.rpm_key:
+ state: present
+ key: "{{ powerflex_common_package_gpg.files[0].path }}"
+ when: powerflex_common_package_gpg.files | length > 0
+
+- name: Install package
+ register: powerflex_common_install_package_output
+ environment: "{{ powerflex_role_environment }}"
+ ansible.builtin.package:
+ name: "{{ powerflex_common_package_file.files[0].path }}"
+ state: "present"
+ disable_gpg_check: "{{ powerflex_gateway_disable_gpg_check | default(false) }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_RedHat.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_RedHat.yml
new file mode 100644
index 000000000..380c9e81d
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_RedHat.yml
@@ -0,0 +1,36 @@
+---
+- name: Copy files
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "/var/tmp/"
+ mode: "0644"
+ register: powerflex_common_file
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*.rpm"
+ - "{{ powerflex_common_file_install_location }}/{{ file_gpg_name }}*"
+
+- name: List the rpm file
+ register: powerflex_common_package_file
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "*{{ file_glob_name }}*.rpm"
+
+- name: List the rpm gpg file
+ register: powerflex_common_package_gpg
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "{{ file_gpg_name }}*"
+
+- name: Import gpg key
+ ansible.builtin.rpm_key:
+ state: present
+ key: "{{ powerflex_common_package_gpg.files[0].path }}"
+ when: powerflex_common_package_gpg.files | length > 0
+
+- name: Install package
+ register: powerflex_common_install_package_output
+ environment: "{{ powerflex_role_environment }}"
+ ansible.builtin.package:
+ name: "{{ powerflex_common_package_file.files[0].path }}"
+ state: "present"
+ disable_gpg_check: "{{ powerflex_gateway_disable_gpg_check | default(false) }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Rocky.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Rocky.yml
new file mode 100644
index 000000000..35d08f875
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Rocky.yml
@@ -0,0 +1,36 @@
+---
+- name: Copy files
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "/var/tmp/"
+ mode: "0644"
+ register: powerflex_common_file
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*"
+ - "{{ powerflex_common_file_install_location }}/{{ file_gpg_name }}*"
+
+- name: List the rpm file
+ register: powerflex_common_package_file
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "*{{ file_glob_name }}*.rpm"
+
+- name: List the rpm gpg file
+ register: powerflex_common_package_gpg
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "{{ file_gpg_name }}*"
+
+- name: Import gpg key
+ ansible.builtin.rpm_key:
+ state: present
+ key: "{{ powerflex_common_package_gpg.files[0].path }}"
+ when: powerflex_common_package_gpg.files | length > 0
+
+- name: Install package
+ register: powerflex_common_install_package_output
+ environment: "{{ powerflex_role_environment }}"
+ ansible.builtin.package:
+ name: "{{ powerflex_common_package_file.files[0].path }}"
+ state: "present"
+ disable_gpg_check: "{{ powerflex_gateway_disable_gpg_check | default(false) }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_SLES.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_SLES.yml
new file mode 100644
index 000000000..380c9e81d
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_SLES.yml
@@ -0,0 +1,36 @@
+---
+- name: Copy files
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "/var/tmp/"
+ mode: "0644"
+ register: powerflex_common_file
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*.rpm"
+ - "{{ powerflex_common_file_install_location }}/{{ file_gpg_name }}*"
+
+- name: List the rpm file
+ register: powerflex_common_package_file
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "*{{ file_glob_name }}*.rpm"
+
+- name: List the rpm gpg file
+ register: powerflex_common_package_gpg
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "{{ file_gpg_name }}*"
+
+- name: Import gpg key
+ ansible.builtin.rpm_key:
+ state: present
+ key: "{{ powerflex_common_package_gpg.files[0].path }}"
+ when: powerflex_common_package_gpg.files | length > 0
+
+- name: Install package
+ register: powerflex_common_install_package_output
+ environment: "{{ powerflex_role_environment }}"
+ ansible.builtin.package:
+ name: "{{ powerflex_common_package_file.files[0].path }}"
+ state: "present"
+ disable_gpg_check: "{{ powerflex_gateway_disable_gpg_check | default(false) }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Ubuntu.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Ubuntu.yml
new file mode 100644
index 000000000..77f794572
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_Ubuntu.yml
@@ -0,0 +1,51 @@
+---
+- name: Copy files
+ ansible.builtin.unarchive:
+ src: "{{ item }}"
+ dest: "/var/tmp/"
+ mode: "0644"
+ register: powerflex_common_ubuntu_tar_file
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*.tar"
+
+- name: Get powerflex_common_siob_file # noqa: no-handler
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "*{{ file_glob_name }}*.siob"
+ register: powerflex_common_siob_file
+ when: powerflex_common_ubuntu_tar_file.changed
+
+- name: Execute chmod siob_extract # noqa: no-handler
+ ansible.builtin.file:
+ path: "/var/tmp/siob_extract"
+ mode: "0755"
+ when: powerflex_common_ubuntu_tar_file.changed
+
+- name: Execute the siob_extract # noqa: no-handler
+ ansible.builtin.command: /var/tmp/siob_extract "{{ powerflex_common_siob_file.files[0].path }}" chdir="/var/tmp"
+ when: powerflex_common_ubuntu_tar_file.changed
+ register: powerflex_common_siob_extract_output
+ changed_when: powerflex_common_siob_extract_output.rc == 0
+
+- name: Copy deb file
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "/var/tmp"
+ mode: "0644"
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*.deb"
+ when: powerflex_common_ubuntu_tar_file.skipped
+
+- name: List the deb file
+ register: powerflex_common_package_file
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "*{{ file_glob_name }}*.deb"
+
+- name: Install package
+ register: powerflex_common_install_package_output
+ environment: "{{ powerflex_role_environment }}"
+ ansible.builtin.package:
+ deb: "{{ powerflex_common_package_file.files[0].path }}"
+ state: "present"
+ disable_gpg_check: "{{ powerflex_gateway_disable_gpg_check | default(false) }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_VMkernel.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_VMkernel.yml
new file mode 100644
index 000000000..3291fe8f6
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_VMkernel.yml
@@ -0,0 +1,50 @@
+---
+- name: Get the acceptance level of the ESXi node
+ register: powerflex_common_get_acceptance_output
+ ansible.builtin.shell: >
+ esxcli software acceptance get
+ changed_when: powerflex_common_get_acceptance_output.stdout != 'PartnerSupported'
+
+- name: Set the acceptance level to PartnerSupported
+ register: powerflex_common_set_acceptance_output
+ ansible.builtin.shell: >
+ esxcli software acceptance set --level=PartnerSupported
+ when: powerflex_common_get_acceptance_output.stdout != 'PartnerSupported'
+ changed_when: powerflex_common_get_acceptance_output.stdout != 'PartnerSupported'
+
+- name: Copy Esxi component and rpm files
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "{{ powerflex_common_esxi_files_location }}"
+ mode: "0644"
+ register: powerflex_common_file
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*"
+ - "{{ powerflex_common_file_install_location }}/{{ file_gpg_name }}*"
+
+- name: List the zip file
+ register: powerflex_common_package_file
+ ansible.builtin.find:
+ paths: "{{ powerflex_common_esxi_files_location }}"
+ patterns: "*{{ file_glob_name }}*.zip"
+
+- name: Install SDC package for ESXi
+ register: powerflex_common_install_package_output
+ ansible.builtin.shell: >
+ esxcli software vib install -d {{ powerflex_common_package_file.files[0].path }} --no-sig-check
+ ignore_errors: true
+ changed_when: "'Reboot Required: true' in powerflex_common_install_package_output.stdout"
+
+- name: Reboot ESXi host
+ register: powerflex_common_reboot_output
+ ansible.builtin.reboot:
+ reboot_timeout: 500
+ msg: "Rebooting the ESXi host."
+ when: "'Reboot Required: true' in powerflex_common_install_package_output.stdout"
+ changed_when: powerflex_common_reboot_output.rebooted
+
+- name: Ensure the driver is loaded for SDC after reboot
+ register: powerflex_common_loaded_driver_output
+ ansible.builtin.shell: >
+ set -o pipefail && esxcli software vib list | grep sdc
+ changed_when: powerflex_common_loaded_driver_output.stdout_lines | length == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_WindowsOS.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_WindowsOS.yml
new file mode 100644
index 000000000..6b8e4b8e8
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_packages_WindowsOS.yml
@@ -0,0 +1,20 @@
+---
+- name: Copy files
+ ansible.windows.win_copy:
+ src: "{{ item }}"
+ dest: "{{ powerflex_common_win_package_location }}"
+ register: powerflex_common_file
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/*{{ file_glob_name }}*.msi"
+
+- name: List the msi file
+ ansible.windows.win_find:
+ paths: "{{ powerflex_common_win_package_location }}"
+ patterns: "*{{ file_glob_name }}*.msi"
+ register: powerflex_common_package_file
+
+- name: Install package
+ register: powerflex_common_install_package_output
+ ansible.windows.win_command: >
+ msiexec.exe /i "{{ powerflex_common_package_file.files[0].path }}" MDM_IP="{{ powerflex_role_environment.MDM_IP }}" /q
+ ignore_errors: true
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_powerflex.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_powerflex.yml
new file mode 100644
index 000000000..98ae4b0c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/install_powerflex.yml
@@ -0,0 +1,8 @@
+---
+- name: Set fact # noqa var-naming[no-role-prefix]
+ ansible.builtin.set_fact:
+ ansible_distribution: "WindowsOS"
+ when: " 'Windows' in ansible_distribution"
+
+- name: Include installation file based on distribution
+ ansible.builtin.include_tasks: "install_packages_{{ ansible_distribution }}.yml"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/main.yml
new file mode 100644
index 000000000..b83b1c148
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+- name: Set fact # noqa var-naming[no-role-prefix]
+ ansible.builtin.set_fact:
+ ansible_distribution: "WindowsOS"
+ when: " 'Windows' in ansible_distribution"
+
+- name: Include vars
+ ansible.builtin.include_vars: "../vars/{{ ansible_distribution }}.yml"
+
+- name: Install required packages # noqa package-latest
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: latest
+ with_items: "{{ powerflex_common_packages }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/CentOS.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/CentOS.yml
new file mode 100644
index 000000000..cadab0571
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/CentOS.yml
@@ -0,0 +1,4 @@
+---
+powerflex_common_packages:
+ - numactl
+ - libaio
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/RedHat.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/RedHat.yml
new file mode 100644
index 000000000..03cedf354
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/RedHat.yml
@@ -0,0 +1,6 @@
+---
+powerflex_common_packages:
+ - numactl
+ - libaio
+ - python3
+ - binutils
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Rocky.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Rocky.yml
new file mode 100644
index 000000000..03cedf354
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Rocky.yml
@@ -0,0 +1,6 @@
+---
+powerflex_common_packages:
+ - numactl
+ - libaio
+ - python3
+ - binutils
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/SLES.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/SLES.yml
new file mode 100644
index 000000000..0f15a62a6
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/SLES.yml
@@ -0,0 +1,4 @@
+---
+powerflex_common_packages:
+ - python3
+ - libapr1
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Ubuntu.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Ubuntu.yml
new file mode 100644
index 000000000..6c5f371ec
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/Ubuntu.yml
@@ -0,0 +1,5 @@
+---
+powerflex_common_packages:
+ - numactl
+ - libaio1
+ - ldap-utils
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/VMkernel.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/VMkernel.yml
new file mode 100644
index 000000000..3cc003a2a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/VMkernel.yml
@@ -0,0 +1,2 @@
+---
+powerflex_common_packages: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/WindowsOS.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/WindowsOS.yml
new file mode 100644
index 000000000..3cc003a2a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_common/vars/WindowsOS.yml
@@ -0,0 +1,2 @@
+---
+powerflex_common_packages: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_config/README.md
new file mode 100644
index 000000000..987773d88
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/README.md
@@ -0,0 +1,165 @@
+# powerflex_config
+
+Role to configure the protection domain, fault set and storage pool.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Usage instructions](#usage-instructions)
+* [Notes](#notes)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td>IP or FQDN of the PowerFlex host.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td>The username of the PowerFlex host.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td>The password of the PowerFlex host.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>false</td>
+ <td>Port of the PowerFlex host.</td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>If C(false), the SSL certificates will not be validated.<br>Configure C(false) only on personally controlled sites where self-signed certificates are used.</td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>powerflex_protection_domain_name</td>
+ <td>false</td>
+ <td>Name of the protection domain.<br></td>
+ <td></td>
+ <td>str</td>
+ <td>config_protection_domain</td>
+ </tr>
+ <tr>
+ <td>powerflex_fault_sets</td>
+ <td>false</td>
+ <td>List of fault sets.<br></td>
+ <td></td>
+ <td>list</td>
+ <td>['fs1','fs2','fs3']</td>
+ </tr>
+ <tr>
+ <td>powerflex_media_type</td>
+ <td>false</td>
+ <td>Media type of the storage pool.<br></td>
+ <td>'SSD', 'HDD', 'TRANSITIONAL'</td>
+ <td>str</td>
+ <td>SSD</td>>
+ </tr>
+ <tr>
+ <td>powerflex_storage_pool_name</td>
+ <td>false</td>
+ <td>Name of the storage pool.<br></td>
+ <td></td>
+ <td>str</td>
+ <td>config_storage_pool</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Configuration of protection domain, fault set and storage pool.
+ ansible.builtin.import_role:
+ name: "powerflex_config"
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_protection_domain_name: "protection_domain"
+ powerflex_fault_sets:
+ - 'fs1'
+ - 'fs2'
+ - 'fs3'
+ powerflex_media_type: 'SSD'
+ powerflex_storage_pool_name: "storage_pool"
+
+```
+
+## Usage instructions
+----
+### To configure the protection domain and storage pool:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Notes
+----
+
+- As a pre-requisite, the Gateway must be installed.
+- TRANSITIONAL media type is supported only during modification.
+
+## Author Information
+------------------
+
+Dell Technologies </br>
+Felix Stephen A (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_config/defaults/main.yml
new file mode 100644
index 000000000..0cb687ecb
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/defaults/main.yml
@@ -0,0 +1,6 @@
+---
+# defaults file for powerflex_config
+powerflex_protection_domain_name: "domain1"
+powerflex_fault_sets: ['fs1', 'fs2', 'fs3']
+powerflex_media_type: 'SSD' # When version is R3
+powerflex_storage_pool_name: "pool1"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/argument_specs.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/argument_specs.yml
new file mode 100644
index 000000000..bd94c306f
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/argument_specs.yml
@@ -0,0 +1,50 @@
+---
+argument_specs:
+ main:
+ short_description: Role to configure the protection domain, fault set and storage pool.
+ description:
+ - Role to configure the protection domain, fault set and storage pool.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: IP or FQDN of the PowerFlex gateway.
+ username:
+ required: true
+ type: str
+ description: The username of the PowerFlex gateway.
+ password:
+ required: true
+ type: str
+ description: The password of the PowerFlex gateway.
+ port:
+ type: int
+ description: Port of the PowerFlex gateway.
+ default: 443
+ validate_certs:
+ description:
+ - If C(false), the SSL certificates will not be validated.
+ - Configure C(false) only on personally controlled sites where self-signed certificates are used.
+ type: bool
+ default: false
+ timeout:
+ description: Timeout.
+ type: int
+ default: 120
+ powerflex_protection_domain_name:
+ type: str
+ description: Name of the protection domain.
+ default: 'config_protection_domain'
+ powerflex_fault_sets:
+ description: List of fault sets.
+ type: list
+ default: ['fs1', 'fs2', 'fs3']
+ powerflex_media_type:
+ description: Media type of the storage pool.
+ type: str
+ choices: ['SSD', 'HDD', 'TRANSITIONAL']
+ default: 'SSD'
+ powerflex_storage_pool_name:
+ description: Name of the storage pool.
+ type: str
+ default: 'config_storage_pool'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/main.yml
new file mode 100644
index 000000000..9924409c8
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/meta/main.yml
@@ -0,0 +1,25 @@
+---
+galaxy_info:
+ author: Felix Stephen A
+ description: Role to configure the protection domain, fault set and storage pool.
+ company: Dell Technologies
+ license: GPL-3.0-only
+ role_name: powerflex_config
+ namespace: dellemc
+
+ min_ansible_version: "2.14.0"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/converge.yml
new file mode 100644
index 000000000..1fb1c2425
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/converge.yml
@@ -0,0 +1,47 @@
+---
+- name: Molecule Test for Configuring Protection Domain
+ hosts: mdm
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Run Config role
+ ansible.builtin.import_role:
+ name: "powerflex_config"
+ register: powerflex_config_result
+
+ - name: "Verifying protection domain creation"
+ ansible.builtin.assert:
+ that:
+ - powerflex_config_add_pd_output.protection_domain_details.name == powerflex_protection_domain_name
+ when: not ansible_check_mode and powerflex_config_add_pd_output.changed
+
+ - name: "Verifying storage pool R2 creation"
+ ansible.builtin.assert:
+ that:
+ - powerflex_config_storage_pool_output.storage_pool_details.name == powerflex_storage_pool_name
+ when: not ansible_check_mode and powerflex_config_storage_pool_output.changed
+
+ - name: "Verifying storage pool R3 creation"
+ ansible.builtin.assert:
+ that:
+ - powerflex_config_storage_pool_output.storage_pool_details.name == powerflex_storage_pool_name
+ when: not ansible_check_mode and powerflex_config_storage_pool_output.changed and powerflex_media_type is not none
+
+ - name: "Verifying protection domain creation in Idempotency"
+ ansible.builtin.assert:
+ that:
+ - powerflex_config_add_pd_output.protection_domain_details.name == powerflex_protection_domain_name
+ when: not ansible_check_mode and powerflex_config_add_pd_output.changed
+
+ - name: "Verifying storage pool R2 creation in Idempotency"
+ ansible.builtin.assert:
+ that:
+ powerflex_config_storage_pool_output.storage_pool_details.name == powerflex_storage_pool_name
+ when: not ansible_check_mode and powerflex_config_storage_pool_output.changed
+
+ - name: "Verifying storage pool R3 creation in Idempotency"
+ ansible.builtin.assert:
+ that:
+ - powerflex_config_storage_pool_output.storage_pool_details.name == powerflex_storage_pool_name
+ when: not ansible_check_mode and powerflex_config_storage_pool_output.changed and powerflex_media_type is not none
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/molecule/configure_protection_domain/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_config/tasks/main.yml
new file mode 100644
index 000000000..f9340f0fd
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/tasks/main.yml
@@ -0,0 +1,79 @@
+---
+- name: Get configured MDM IP addresses
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ state: "present"
+ register: powerflex_config_mdm_ip_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Set fact - PowerFlex version and MDM primary hostname
+ ansible.builtin.set_fact:
+ powerflex_config_array_version: "{{ powerflex_config_mdm_ip_result.mdm_cluster_details.master.versionInfo[1] }}"
+ powerflex_config_mdm_primary_hostname: "{{ hostvars[groups['mdm'][0]]['inventory_hostname'] }}"
+
+- name: Login to primary MDM of PowerFlex 3.6
+ ansible.builtin.command: scli --login --username {{ username }} --password "{{ password }}"
+ run_once: true
+ register: powerflex_config_login_output
+ changed_when: powerflex_config_login_output.rc == 0
+ delegate_to: "{{ powerflex_config_mdm_primary_hostname }}"
+ when: powerflex_config_array_version == '3'
+
+- name: Login to primary MDM of PowerFlex 4.5
+ ansible.builtin.command: scli --login --username {{ username }} --management_system_ip {{ hostname }} --password "{{ password }}"
+ run_once: true
+ register: powerflex_config_login_output
+ changed_when: powerflex_config_login_output.rc == 0
+ delegate_to: "{{ powerflex_config_mdm_primary_hostname }}"
+ when: powerflex_config_array_version == '4'
+
+- name: Create the protection domain
+ dellemc.powerflex.protection_domain:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ protection_domain_name: "{{ powerflex_protection_domain_name }}"
+ is_active: "{{ is_active | default(omit) }}"
+ network_limits: "{{ network_limits | default(omit) }}"
+ rf_cache_limits: "{{ rf_cache_limits | default(omit) }}"
+ state: "present"
+ register: powerflex_config_add_pd_output
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Add fault set
+ ansible.builtin.command: scli --add_fault_set --protection_domain_name "{{ powerflex_protection_domain_name }}" --fault_set_name "{{ item }}"
+ with_items: "{{ powerflex_fault_sets }}"
+ run_once: true
+ delegate_to: "{{ powerflex_config_mdm_primary_hostname }}"
+ register: powerflex_config_add_fs_output
+ ignore_errors: true
+ changed_when: powerflex_config_add_fs_output.rc == 0
+ when:
+ - powerflex_fault_sets is defined
+
+- name: Create a new storage pool.
+ dellemc.powerflex.storagepool:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ storage_pool_name: "{{ powerflex_storage_pool_name }}"
+ protection_domain_name: "{{ powerflex_protection_domain_name }}"
+ media_type: "{{ powerflex_media_type | default(omit) }}"
+ state: "present"
+ register: powerflex_config_storage_pool_output
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Enable zero-padding
+ ansible.builtin.command: |
+ scli --modify_zero_padding_policy --protection_domain_name
+ {{ powerflex_protection_domain_name }} --storage_pool_name {{ powerflex_storage_pool_name }} --enable_zero_padding
+ run_once: true
+ register: powerflex_config_enable_zero_padding_output
+ changed_when: powerflex_config_enable_zero_padding_output.rc == 0
+ delegate_to: "{{ powerflex_config_mdm_primary_hostname }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_config/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_config/vars/main.yml
new file mode 100644
index 000000000..ac3d9b959
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_config/vars/main.yml
@@ -0,0 +1,2 @@
+---
+# vars file for powerflex_config
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/README.md
new file mode 100644
index 000000000..eac43ab78
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/README.md
@@ -0,0 +1,160 @@
+# powerflex_gateway
+
+Role to manage the installation and uninstallation of Powerflex Gateway.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Notes](#notes)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>false</td>
+ <td>Location of installation, compatible installation software package based on the operating system of the node.
+ <br> The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>path</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_is_redundant</td>
+ <td>false</td>
+ <td>Is the gateway redundant (will install keepalived).<br></td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_admin_password</td>
+ <td>true</td>
+ <td>Admin password for the Powerflex gateway.<br></td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_http_port</td>
+ <td>false</td>
+ <td>Powerflex gateway HTTP port.<br></td>
+ <td></td>
+ <td>int</td>
+ <td>80</td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_https_port</td>
+ <td>false</td>
+ <td>Powerflex gateway HTTPS port.<br></td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_virtual_ip</td>
+ <td>false</td>
+ <td>Virtual IP address of Powerflex gateway.<br></td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_virtual_interface</td>
+ <td>false</td>
+ <td>Virtual interface of Powerflex gateway.<br></td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_state</td>
+ <td>false</td>
+ <td>Specify state of gateway.<br></td>
+ <td>absent, present</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+ <tr>
+ <td>powerflex_gateway_skip_java</td>
+ <td>false</td>
+ <td>Specify whether to install the java or not.<br></td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Install and configure powerflex gateway
+ ansible.builtin.import_role:
+ name: powerflex_gateway
+ vars:
+ powerflex_common_file_install_location: "/opt/scaleio/rpm"
+ powerflex_gateway_admin_password: password
+ powerflex_gateway_state: present
+
+ - name: Uninstall powerflex gateway
+ ansible.builtin.import_role:
+ name: powerflex_gateway
+ vars:
+ powerflex_gateway_state: absent
+
+```
+
+## Notes
+- Supported only in PowerFlex version 3.6.
+
+## Usage instructions
+----
+### To install all dependency packages, including gateway, on node:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+
+### To uninstall gateway:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Bhavneet Sharma (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/defaults/main.yml
new file mode 100644
index 000000000..011911837
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/defaults/main.yml
@@ -0,0 +1,17 @@
+---
+# Is the gateway redundant (will install keepalived)
+powerflex_gateway_is_redundant: false
+# Virtual IP if redundant
+powerflex_gateway_virtual_ip: ''
+# Interface to attach the virtual ip
+powerflex_gateway_virtual_interface: eth1
+# Skip Java installation for PowerFlex (assume it's on the system)
+powerflex_gateway_skip_java: false
+# Disable GPG check to install PowerFlex gateway
+powerflex_gateway_disable_gpg_check: true
+powerflex_gateway_user_properties_file: /opt/emc/scaleio/gateway/webapps/ROOT/WEB-INF/classes/gatewayUser.properties
+powerflex_gateway_catalina_properties_file: /opt/emc/scaleio/gateway/conf/catalina.properties
+file_glob_name: gateway
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_mdm_ips }}"
+ GATEWAY_ADMIN_PASSWORD: "{{ powerflex_gateway_admin_password }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/handlers/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/handlers/main.yml
new file mode 100644
index 000000000..ae7f1163f
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/handlers/main.yml
@@ -0,0 +1,6 @@
+---
+- name: Restart keepalived
+ ansible.builtin.service:
+ name: "keepalived"
+ state: "restarted"
+ enabled: true
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/argument_specs.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/argument_specs.yml
new file mode 100644
index 000000000..2fe8f150e
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/argument_specs.yml
@@ -0,0 +1,47 @@
+---
+argument_specs:
+ main:
+ short_description: Role to manage the installation and uninstallation of
+ PowerFlex gateway
+ description:
+ - Role to manage the installation and uninstallation of PowerFlex gateway.
+ options:
+ powerflex_common_file_install_location:
+ type: path
+ description:
+ - Location of installation, compatible installation software package
+ based on the operating system of the node.
+ - The files can be downloaded from the Dell Product support page for
+ the PowerFlex software.
+ default: '/var/tmp'
+ powerflex_gateway_is_redundant:
+ type: bool
+ description: Is the gateway redundant (will install keepalived)
+ default: false
+ powerflex_gateway_admin_password:
+ required: true
+ type: str
+ description: Admin password for the PowerFlex gateway.
+ powerflex_gateway_http_port:
+ type: int
+ description: PowerFlex gateway HTTP port.
+ default: 80
+ powerflex_gateway_https_port:
+ type: int
+ description: PowerFlex gateway HTTPS port.
+ default: 443
+ powerflex_gateway_virtual_ip:
+ type: str
+ description: Virtual IP address of PowerFlex gateway.
+ powerflex_gateway_virtual_interface:
+ type: str
+ description: Virtual interface of PowerFlex gateway.
+ powerflex_gateway_state:
+ type: str
+ description: State of the PowerFlex gateway.
+ choices: ['present', 'absent']
+ default: 'present'
+ powerflex_gateway_skip_java:
+ type: bool
+ description: Specifies whether to install java or not.
+ default: false
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/main.yml
new file mode 100644
index 000000000..11db01ec5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/meta/main.yml
@@ -0,0 +1,28 @@
+---
+galaxy_info:
+ role_name: powerflex_gateway
+ namespace: dellemc
+ author: Bhavneet Sharma
+ description: Role to manage the installation and uninstallation of Powerflex gateway
+ company: Dell Technologies
+ license: GPL-3.0-only
+ min_ansible_version: "2.14.0"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+
+ - name: Ubuntu
+ versions:
+ - jammy
+
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+
+dependencies:
+ - role: powerflex_common
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/converge.yml
new file mode 100644
index 000000000..92183f3dc
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/converge.yml
@@ -0,0 +1,29 @@
+---
+- name: Install gateway
+ hosts: gateway
+ gather_facts: true
+ tasks:
+ - name: Install and configure powerflex gateway
+ ansible.builtin.import_role:
+ name: "powerflex_gateway"
+ vars:
+ powerflex_gateway_state: present
+ register: powerflex_gateway_result_molecule
+
+ - name: Verifying installation package in check mode
+ ansible.builtin.assert:
+ that:
+ - " 'No changes made, but would have if not in check mode' in powerflex_common_install_package_output.msg"
+ when: ansible_check_mode
+
+ - name: Verifying installation package
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: Verifying installation package in idempotency
+ ansible.builtin.assert:
+ that:
+ - " 'Nothing to do' in powerflex_common_install_package_output.msg"
+ when: not ansible_check_mode and not powerflex_common_install_package_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/converge.yml
new file mode 100644
index 000000000..258173d9a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/converge.yml
@@ -0,0 +1,32 @@
+---
+- name: Install gateway with invalid rpm path
+ hosts: gateway
+ gather_facts: true
+ tasks:
+ - name: Install and configure powerflex gateway with no rpm
+ ansible.builtin.import_role:
+ name: "powerflex_gateway"
+ vars:
+ powerflex_common_file_install_location: "/opt/empty"
+ powerflex_gateway_state: present
+ ignore_errors: true
+ register: powerflex_gateway_install_config_no_rpm_result
+
+ - name: Verifying failure of install package with respect to no rpm file
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length == 0
+
+ - name: Install and configure powerflex gateway with wrong file path
+ ansible.builtin.import_role:
+ name: "powerflex_gateway"
+ vars:
+ powerflex_common_file_install_location: "/opt/aaab"
+ powerflex_gateway_state: present
+ ignore_errors: true
+ register: powerflex_gateway_install_config_wrong_path_result
+
+ - name: Verifying failure of install package with wrong file path
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/molecule.yml
new file mode 100644
index 000000000..93cad84c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_installation_invalid_path_rpm/molecule.yml
@@ -0,0 +1,4 @@
+---
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/converge.yml
new file mode 100644
index 000000000..6342d5f25
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/converge.yml
@@ -0,0 +1,48 @@
+---
+- name: Uninstall gateway
+ hosts: gateway
+ gather_facts: true
+ tasks:
+ - name: Uninstall powerflex gateway
+ ansible.builtin.import_role:
+ name: "powerflex_gateway"
+ vars:
+ powerflex_gateway_state: 'absent'
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_gateway_uninstall_output.msg == "Check mode: No changes made, but would have if not in check mode"
+ - powerflex_gateway_uninstall_output.changed is true
+ when: ansible_check_mode and ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying uninstall package in converge
+ ansible.builtin.assert:
+ that:
+ - " 'Removed:' in powerflex_gateway_uninstall_output.results[0].results[0]"
+ when: not ansible_check_mode and powerflex_gateway_uninstall_output.changed and ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_gateway_uninstall_output.results[0].msg == 'Nothing to do'
+ when: not ansible_check_mode and not powerflex_gateway_uninstall_output.changed and ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_gateway_uninstall_deb_output.msg == "Check mode: No changes made, but would have if not in check mode"
+ - powerflex_gateway_uninstall_deb_output.changed is true
+ when: ansible_check_mode and ansible_distribution == "Ubuntu"
+
+ - name: Verifying uninstall package in converge
+ ansible.builtin.assert:
+ that:
+ - " 'Removed:' in powerflex_gateway_uninstall_deb_output.results[0].results[0]"
+ when: not ansible_check_mode and powerflex_gateway_uninstall_deb_output.changed and ansible_distribution == "Ubuntu"
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_gateway_uninstall_deb_output.results[0].msg == 'Nothing to do'
+ when: not ansible_check_mode and not powerflex_gateway_uninstall_deb_output.changed and ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/molecule/gateway_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_gateway.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_gateway.yml
new file mode 100644
index 000000000..58bbd1a08
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_gateway.yml
@@ -0,0 +1,52 @@
+---
+- name: Set Fact the powerflex_mdm_ips
+ ansible.builtin.set_fact:
+ powerflex_mdm_ips: "{{ hostvars[groups['mdm'][0]]['ansible_host'] }},{{ hostvars[groups['mdm'][1]]['ansible_host'] }}"
+
+- name: Install java
+ ansible.builtin.include_tasks: "../../powerflex_common/tasks/install_java_{{ ansible_distribution }}.yml"
+ when: not powerflex_gateway_skip_java
+
+- name: Set gateway admin password
+ ansible.builtin.set_fact:
+ token: "{{ powerflex_gateway_admin_password }}"
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Include install_keepalived.yml
+ ansible.builtin.include_tasks: install_keepalived.yml
+ when: powerflex_gateway_is_redundant == "true"
+
+- name: Configure gateway with MDM addresses
+ ansible.builtin.lineinfile:
+ name: "{{ powerflex_gateway_user_properties_file }}"
+ regexp: '^mdm.ip.addresses'
+ line: "mdm.ip.addresses={{ powerflex_mdm_ips }}"
+ ignore_errors: "{{ ansible_check_mode }}"
+
+- name: Configure gateway to accept certificates
+ ansible.builtin.lineinfile:
+ name: "{{ powerflex_gateway_user_properties_file }}"
+ regexp: '^security.bypass_certificate_check'
+ line: "security.bypass_certificate_check=true"
+ ignore_errors: "{{ ansible_check_mode }}"
+
+- name: Configure gateway http port
+ ansible.builtin.lineinfile:
+ name: "{{ powerflex_gateway_catalina_properties_file }}"
+ regexp: '^http.port'
+ line: "http.port={{ powerflex_gateway_http_port }}"
+ ignore_errors: "{{ ansible_check_mode }}"
+
+- name: Configure gateway https port
+ ansible.builtin.lineinfile:
+ name: "{{ powerflex_gateway_catalina_properties_file }}"
+ regexp: '^ssl.port'
+ line: "ssl.port={{ powerflex_gateway_https_port }}"
+ ignore_errors: "{{ ansible_check_mode }}"
+
+- name: Restart service PowerFlex Gateway
+ ansible.builtin.service:
+ name: scaleio-gateway.service
+ state: restarted
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_keepalived.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_keepalived.yml
new file mode 100644
index 000000000..df6fd9dac
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/install_keepalived.yml
@@ -0,0 +1,28 @@
+---
+- name: Include vars
+ ansible.builtin.include_vars: "../vars/{{ ansible_distribution }}.yml"
+
+- name: Install required packages
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: present
+ with_items: "{{ keepalived_packages }}"
+
+- name: Set the priority of keepalived
+ ansible.builtin.set_fact:
+ keepalived_priority: 100
+ run_once: true
+
+- name: Set the priority of keepalived if not defined
+ ansible.builtin.set_fact:
+ keepalived_priority: 101
+ when: keepalived_priority is not defined
+
+- name: Configure keepalived
+ ansible.builtin.template:
+ src: keepalived.conf.j2
+ dest: "{{ keepalived_config_file_location }}/keepalived.conf"
+ mode: '0600'
+ owner: root
+ group: root
+ notify: restart keepalived
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/main.yml
new file mode 100644
index 000000000..80af948e2
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Install Powerflex gateway
+ ansible.builtin.include_tasks: install_gateway.yml
+ when: powerflex_gateway_state == "present"
+
+- name: Uninstall Powerflex gateway
+ ansible.builtin.include_tasks: uninstall_gateway.yml
+ when: powerflex_gateway_state == "absent"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/uninstall_gateway.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/uninstall_gateway.yml
new file mode 100644
index 000000000..39645d5a3
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/tasks/uninstall_gateway.yml
@@ -0,0 +1,20 @@
+---
+- name: Uninstall package
+ register: powerflex_gateway_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-gateway
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+- name: Uninstall deb package
+ register: powerflex_gateway_uninstall_deb_output
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - emc-scaleio-gateway
+ when: ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/templates/keepalived.conf.j2 b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/templates/keepalived.conf.j2
new file mode 100644
index 000000000..b9896823e
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/templates/keepalived.conf.j2
@@ -0,0 +1,18 @@
+vrrp_script chk_gateway { # Requires keepalived-1.1.13
+ script "killall -0 scaleio-gateway-wd.bash" # cheaper than pidof
+ interval 2 # check every 2 seconds
+ weight 2 # add 2 points of prio if OK
+}
+
+vrrp_instance gateway_vi_1 {
+ interface {{ powerflex_gateway_virtual_interface }}
+ state MASTER
+ virtual_router_id 51
+ priority {{ keepalived_priority }} # 101 on master, 100 on backup
+ virtual_ipaddress {
+ {{ powerflex_gateway_virtual_ip }}
+ }
+ track_script {
+ chk_gateway
+ }
+}
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/CentOS.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/CentOS.yml
new file mode 100644
index 000000000..cbb2739c1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/CentOS.yml
@@ -0,0 +1,4 @@
+---
+keepalived_packages:
+ - keepalived
+keepalived_config_file_location: /etc/keepalived
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/RedHat.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/RedHat.yml
new file mode 100644
index 000000000..cbb2739c1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/RedHat.yml
@@ -0,0 +1,4 @@
+---
+keepalived_packages:
+ - keepalived
+keepalived_config_file_location: /etc/keepalived
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/SLES.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/SLES.yml
new file mode 100644
index 000000000..cbb2739c1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/SLES.yml
@@ -0,0 +1,4 @@
+---
+keepalived_packages:
+ - keepalived
+keepalived_config_file_location: /etc/keepalived
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/Ubuntu.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/Ubuntu.yml
new file mode 100644
index 000000000..cbb2739c1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/Ubuntu.yml
@@ -0,0 +1,4 @@
+---
+keepalived_packages:
+ - keepalived
+keepalived_config_file_location: /etc/keepalived
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/main.yml
new file mode 100644
index 000000000..6de60b1d3
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_gateway/vars/main.yml
@@ -0,0 +1,6 @@
+---
+file_glob_name: gateway
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_mdm_ips }}"
+ GATEWAY_ADMIN_PASSWORD: "{{ powerflex_gateway_admin_password }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/README.md
new file mode 100644
index 000000000..2ae19c9a1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/README.md
@@ -0,0 +1,170 @@
+# powerflex_lia
+
+Role to manage the installation and uninstallation of Powerflex LIA.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td>IP or FQDN of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td>10.1.1.1</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td>The username of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td>admin</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td>The password of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td>password</td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>false</td>
+ <td>Port</td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>If C(false), the SSL certificates will not be validated.<br>Configure C(false) only on personally controlled sites where self-signed certificates are used.</td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>timeout</td>
+ <td>false</td>
+ <td>Timeout</td>
+ <td></td>
+ <td>int</td>
+ <td>120</td>
+ </tr>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>true</td>
+ <td>Location of installation and rpm gpg files to be installed.
+ <br>The required, compatible installation software package based on the operating system of the node. The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>str</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_lia_token</td>
+ <td>true</td>
+ <td>Lia password for node management.</td>
+ <td></td>
+ <td>str</td>
+ <td>Cluster1!</td>
+ </tr>
+ <tr>
+ <td>powerflex_lia_state</td>
+ <td>false</td>
+ <td>Specify state of LIA.<br></td>
+ <td>absent, present</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Install and configure PowerFlex LIA
+ ansible.builtin.import_role:
+ name: powerflex_lia
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_lia_token: "Cluster1!"
+ powerflex_lia_state: present
+
+ - name: Uninstall powerflex LIA
+ ansible.builtin.import_role:
+ name: powerflex_lia
+ vars:
+ powerflex_lia_state: absent
+
+```
+
+## Usage instructions
+----
+### To install all dependency packages, including LIA, on node:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+### To uninstall LIA:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies
+Pavan Mudunuri (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/defaults/main.yml
new file mode 100644
index 000000000..d69a82e0a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+file_glob_name: lia
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_lia_mdm_ips }}"
+ TOKEN: "{{ powerflex_lia_token }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/meta/main.yml
new file mode 100644
index 000000000..ea089a471
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/meta/main.yml
@@ -0,0 +1,27 @@
+---
+galaxy_info:
+ author: Pavan Mudunuri
+ description: Role to manage the installation and uninstallation of Powerflex LIA.
+ company: Dell Technologies
+ role_name: powerflex_lia
+ namespace: dellemc
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.14.0"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/converge.yml
new file mode 100644
index 000000000..7774d935b
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/converge.yml
@@ -0,0 +1,30 @@
+---
+- name: Molecule Test for installation of LIA
+ hosts: lia
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Install and configure Powerflex LIA
+ ansible.builtin.import_role:
+ name: powerflex_lia
+ vars:
+ powerflex_lia_state: present
+
+ - name: Verifying install package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_install_package_output.msg == "Check mode: No changes made"
+ when: ansible_check_mode
+
+ - name: Verifying installation package in normal mode
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: Verifying installation package in Idempotency mode
+ ansible.builtin.assert:
+ that:
+ - "'Nothing to do' in powerflex_common_install_package_output.msg"
+ when: not ansible_check_mode and not powerflex_common_install_package_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_install/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/converge.yml
new file mode 100644
index 000000000..d517ac2b6
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/converge.yml
@@ -0,0 +1,34 @@
+---
+- name: Molecule Test for installation of LIA with invalid rpm path, rpm file
+ hosts: lia
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Install and configure powerflex LIA with no rpm
+ ansible.builtin.import_role:
+ name: powerflex_lia
+ vars:
+ powerflex_common_file_install_location: "/opt/empty"
+ powerflex_lia_state: present
+ register: powerflex_lia_no_rpm_result
+ ignore_errors: true
+
+ - name: Verifying failure of install package with respect to no rpm file in normal mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length | int == 0
+
+ - name: Install and configure powerflex lia with wrong file path
+ ansible.builtin.import_role:
+ name: powerflex_lia
+ vars:
+ powerflex_common_file_install_location: "/opt/aaab"
+ powerflex_lia_state: present
+ register: powerflex_lia_wrong_file_path_result
+ ignore_errors: true
+
+ - name: Verifying failure of install package with wrong file path in normal mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length | int == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/molecule.yml
new file mode 100644
index 000000000..93cad84c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_installation_invalid_path_rpm/molecule.yml
@@ -0,0 +1,4 @@
+---
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/converge.yml
new file mode 100644
index 000000000..531359673
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/converge.yml
@@ -0,0 +1,30 @@
+---
+- name: Molecule Test for uninstallation of LIA
+ hosts: lia
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Uninstall powerflex lia
+ ansible.builtin.import_role:
+ name: powerflex_lia
+ vars:
+ powerflex_lia_state: 'absent'
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_lia_uninstall_output.msg == "Check mode: No changes made
+ when: ansible_check_mode
+
+ - name: Verifying uninstall package in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Removed: EMC-ScaleIO-lia' in powerflex_lia_uninstall_output.results[0].results[0]"
+ when: not ansible_check_mode and powerflex_lia_uninstall_output.changed
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that:
+ - "'Nothing to do' in powerflex_lia_uninstall_output.results[0].msg"
+ when: not ansible_check_mode and not powerflex_lia_uninstall_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/molecule/lia_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/install_lia.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/install_lia.yml
new file mode 100644
index 000000000..4b987b80e
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/install_lia.yml
@@ -0,0 +1,22 @@
+---
+- name: Set facts for MDM counts
+ ansible.builtin.set_fact:
+ mdm_count: "{{ groups['mdm'] | length }}"
+
+- name: Set facts for powerflex_lia_tertiary_ip
+ ansible.builtin.set_fact:
+ powerflex_lia_tertiary_ip: "{{ hostvars[groups['mdm'][2]]['ansible_host'] }}"
+ when: mdm_count | int > 2
+
+- name: Set facts for powerflex_lia_mdm_ips if mdm_count is 2
+ ansible.builtin.set_fact:
+ powerflex_lia_mdm_ips: "{{ hostvars[groups['mdm'][0]]['ansible_host'] }},{{ hostvars[groups['mdm'][1]]['ansible_host'] }}"
+ when: mdm_count | int == 2
+
+- name: Set facts for powerflex_lia_mdm_ips if mdm_count is more than 2
+ ansible.builtin.set_fact:
+ powerflex_lia_mdm_ips: "{{ hostvars[groups['mdm'][0]]['ansible_host'] }},{{ hostvars[groups['mdm'][1]]['ansible_host'] }},{{ powerflex_lia_tertiary_ip }}"
+ when: mdm_count | int > 2
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/main.yml
new file mode 100644
index 000000000..f04a3ff75
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Install LIA
+ ansible.builtin.include_tasks: install_lia.yml
+ when: powerflex_lia_state == 'present'
+
+- name: Uninstall LIA
+ ansible.builtin.include_tasks: uninstall_lia.yml
+ when: powerflex_lia_state == 'absent'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/uninstall_lia.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/uninstall_lia.yml
new file mode 100644
index 000000000..3cac9b41d
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/tasks/uninstall_lia.yml
@@ -0,0 +1,19 @@
+---
+- name: Uninstall package
+ register: powerflex_lia_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-lia
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+- name: Uninstall deb package
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - emc-scaleio-lia
+ when: ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_lia/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/vars/main.yml
new file mode 100644
index 000000000..6877f3723
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_lia/vars/main.yml
@@ -0,0 +1,6 @@
+---
+file_glob_name: lia
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_lia_mdm_ips }}"
+ TOKEN: "{{ powerflex_lia_token }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/README.md
new file mode 100644
index 000000000..aa54a27a0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/README.md
@@ -0,0 +1,142 @@
+# powerflex_mdm
+
+Role to manage the installation and uninstallation of Powerflex MDM.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Usage instructions](#usage-instructions)
+* [Notes](#notes)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+ansible.posix
+community.general
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>true</td>
+ <td>Location of installation and rpm gpg files to be installed.
+ <br> The required, compatible installation software package based on the operating system of the node.
+ <br> The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>str</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_mdm_password</td>
+ <td>true</td>
+ <td>Password for mdm cluster.<br></td>
+ <td></td>
+ <td>str</td>
+ <td>Password123</td>
+ </tr>
+ <tr>
+ <td>powerflex_mdm_state</td>
+ <td>false</td>
+ <td>Specify state of MDM.<br></td>
+ <td>absent, present</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+ <tr>
+ <td>powerflex_mdm_virtual_ip</td>
+ <td>false</td>
+ <td>Virtual IP address of MDM.<br></td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_mdm_cert_password</td>
+ <td>false</td>
+ <td>The password to generate the certificate cli.
+ <br>Required while installing MDM for Powerlex 4.x.<br></td>
+ <td></td>
+ <td>str</td>
+ <td>Password123!</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: "Install and configure powerflex mdm"
+ ansible.builtin.import_role:
+ name: "powerflex_mdm"
+ vars:
+ powerflex_common_file_install_location: "/opt/scaleio/rpm"
+ powerflex_mdm_password: password
+ powerflex_mdm_state: present
+
+ - name: "Uninstall powerflex mdm"
+ ansible.builtin.import_role:
+ name: "powerflex_mdm"
+ vars:
+ powerflex_mdm_state: absent
+
+```
+
+## Usage instructions
+----
+### To install all dependency packages, including mdm, on node:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+### To uninstall mdm:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Notes
+- The ```community.general``` collection must be installed for MDM installation on SLES OS.
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Bhavneet Sharma (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/defaults/main.yml
new file mode 100644
index 000000000..340da8bb8
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+# Skip Java installation for powerflex (assume it's on the system)
+powerflex_skip_java: false
+powerflex_mdm_primary_hostname: ''
+powerflex_mdm_primary_ip: ''
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_mdm_ips }}"
+ MDM_ROLE_IS_MANAGER: 1
+file_glob_name: mdm
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/argument_spec.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/argument_spec.yml
new file mode 100644
index 000000000..be80c1970
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/argument_spec.yml
@@ -0,0 +1,28 @@
+---
+argument_specs:
+ main:
+ version_added: "1.8.0"
+ short_description: Role to manage the installation and uninstallation of Powerflex MDM
+ description:
+ - Role to manage the installation and uninstallation of Powerflex MDM.
+ options:
+ powerflex_mdm_state:
+ required: true
+ type: str
+ description: State of the Powerflex MDM.
+ powerflex_mdm_password:
+ required: true
+ type: str
+ description: Password for the Powerflex MDM.
+ powerflex_common_file_install_location:
+ required: true
+ type: str
+ description: Common file installation location.
+ powerflex_mdm_virtual_ip:
+ type: str
+ description: Virtual IP address of MDM.
+ powerflex_mdm_cert_password:
+ type: str
+ description:
+ - Password to generate cli certificate for MDM.
+ - Required while installing MDM for Powerlex 4.x.
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/main.yml
new file mode 100644
index 000000000..889114f46
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/meta/main.yml
@@ -0,0 +1,29 @@
+---
+galaxy_info:
+ author: Bhavneet Sharma
+ description: Role to manage the installation and uninstallation of Powerflex MDM.
+ company: Dell Technologies
+ role_name: powerflex_mdm
+ namespace: dellemc
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.14.0"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+dependencies:
+ - role: powerflex_common
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/converge.yml
new file mode 100644
index 000000000..707de56fe
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/converge.yml
@@ -0,0 +1,63 @@
+---
+- name: MDM installation
+ hosts: mdm
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ tasks:
+ - name: Install common packages
+ ansible.builtin.import_role:
+ name: powerflex_common
+
+ - name: Install and configure Powerflex MDM
+ ansible.builtin.import_role:
+ name: powerflex_mdm
+ vars:
+ powerflex_mdm_state: present
+
+ - name: Verifying install package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_install_package_output.msg == "Check mode: No changes made"
+ when: ansible_check_mode
+
+ - name: Verifying installation package in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: Verifying add primary mdm in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Successfully created the MDM Cluster' in powerflex_mdm_add_primary_output.stdout"
+ when: not ansible_check_mode and powerflex_mdm_add_primary_output.changed
+
+ - name: Verifying add secondary mdm in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Successfully added a standby MDM' in powerflex_mdm_add_secondary_output.stdout"
+ when: not ansible_check_mode and powerflex_mdm_add_secondary_output.changed
+
+ - name: Verifying add tertiary mdm in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Successfully added a standby MDM' in powerflex_mdm_add_tertiary_output.stdout"
+ when: not ansible_check_mode and powerflex_mdm_add_tertiary_output.changed
+
+ - name: Verifying primary mdm configuration in Idempotency
+ ansible.builtin.assert:
+ that:
+ - "'The Primary MDM is already configured' in powerflex_mdm_add_primary_output.stderr_lines[0]"
+ when: not ansible_check_mode and not powerflex_mdm_add_primary_output.changed
+
+ - name: Verifying secondary mdm configuration in Idempotency
+ ansible.builtin.assert:
+ that:
+ - "'An MDM with the same name already exists' in powerflex_mdm_add_secondary_output.stderr_lines[0]"
+ when: not ansible_check_mode and not powerflex_mdm_add_secondary_output.changed
+
+ - name: Verifying tertiary mdm configuration in Idempotency
+ ansible.builtin.assert:
+ that:
+ - "'An MDM with the same name already exists' in powerflex_mdm_add_tertiary_output.stderr_lines[0]"
+ when: not ansible_check_mode and powerflex_mdm_tertiary_ip is defined and not powerflex_mdm_add_tertiary_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_installation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/converge.yml
new file mode 100644
index 000000000..ede8baf5a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/converge.yml
@@ -0,0 +1,53 @@
+---
+- name: MDM uninstallation
+ hosts: mdm
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ tasks:
+ - name: Uninstall powerflex MDM
+ ansible.builtin.import_role:
+ name: powerflex_mdm
+ vars:
+ powerflex_mdm_state: 'absent'
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_mdm_uninstall_output.msg == "Check mode: No changes made"
+ when: ansible_check_mode
+
+ - name: Verifying remove secondary mdm in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Successfully removed the standby MDM' in powerflex_mdm_remove_secondary.stdout"
+ when: not ansible_check_mode and powerflex_mdm_remove_secondary.changed
+
+ - name: Verifying remove tertiary mdm in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Successfully removed the standby MDM' in powerflex_mdm_remove_tertiary.stdout"
+ when: not ansible_check_mode and powerflex_mdm_tertiary_ip is defined and powerflex_mdm_remove_tertiary.changed
+
+ - name: Verifying uninstall package in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Removed: EMC-ScaleIO-mdm' in powerflex_mdm_uninstall_output.results[0].results[0]"
+ when: not ansible_check_mode and powerflex_mdm_uninstall_output.changed
+
+ - name: Verifying remove secondary mdm in Idempotency
+ ansible.builtin.assert:
+ that:
+ - "'No such file or directory' in powerflex_mdm_remove_secondary.msg"
+ when: not ansible_check_mode and not powerflex_mdm_remove_secondary.changed
+
+ - name: Verifying remove tertiary mdm in Idempotency
+ ansible.builtin.assert:
+ that:
+ - "'No such file or directory' in powerflex_mdm_remove_tertiary.msg"
+ when: not ansible_check_mode and powerflex_mdm_tertiary_ip is defined and not powerflex_mdm_remove_tertiary.changed
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that:
+ - "'Nothing to do' in powerflex_mdm_uninstall_output.results[0].msg"
+ when: not ansible_check_mode and not powerflex_mdm_uninstall_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/molecule/mdm_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/add_certs.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/add_certs.yml
new file mode 100644
index 000000000..f517d5229
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/add_certs.yml
@@ -0,0 +1,168 @@
+---
+- name: Generate CA certificate
+ register: powerflex_mdm_generate_mgmt_ca_cert
+ ansible.builtin.command: python3 certificate_generator_MDM_USER.py --generate_ca mgmt_ca.pem
+ args:
+ chdir: /opt/emc/scaleio/mdm/cfg
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ changed_when: powerflex_mdm_generate_mgmt_ca_cert.rc == 0
+
+- name: Create CLI certificate
+ register: powerflex_mdm_generate_cli_cert
+ ansible.builtin.command: >
+ python3 certificate_generator_MDM_USER.py --generate_cli cli_certificate.p12 -CA mgmt_ca.pem --password {{ powerflex_mdm_cert_password }}
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ args:
+ chdir: /opt/emc/scaleio/mdm/cfg
+ changed_when: powerflex_mdm_generate_cli_cert.rc == 0
+
+- name: Create MDM certificate
+ register: powerflex_mdm_generate_mdm_cert
+ ansible.builtin.command: python3 certificate_generator_MDM_USER.py --generate_mdm mdm_certificate.pem -CA mgmt_ca.pem
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ args:
+ chdir: /opt/emc/scaleio/mdm/cfg
+ changed_when: powerflex_mdm_generate_mdm_cert.rc == 0
+
+- name: Create additional MDM certificates
+ register: powerflex_mdm_generate_additional_mdm_cert
+ ansible.builtin.command: python3 certificate_generator_MDM_USER.py --generate_mdm sec_mdm_certificate.pem -CA mgmt_ca.pem
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ args:
+ chdir: /opt/emc/scaleio/mdm/cfg
+ changed_when: powerflex_mdm_generate_additional_mdm_cert.rc == 0
+
+- name: Fetch all certs to localhost
+ register: powerflex_mdm_fetch_certs
+ ansible.builtin.fetch:
+ src: /opt/emc/scaleio/mdm/cfg/{{ item }}
+ dest: /tmp/
+ flat: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ with_items:
+ - sec_mdm_certificate.pem
+ - cli_certificate.p12
+ - mgmt_ca.pem
+
+- name: Copy MDM certificates to Secondary manager MDM node
+ register: powerflex_mdm_copy_additional_certs_to_secondary
+ ansible.builtin.copy:
+ src: /tmp/sec_mdm_certificate.pem
+ dest: /opt/emc/scaleio/mdm/cfg/mdm_certificate.pem
+ mode: preserve
+ delegate_to: "{{ powerflex_mdm_secondary_hostname }}"
+ when: powerflex_mdm_secondary_ip is defined
+
+- name: Copy CLI certificates to Secondary manager MDM node
+ register: powerflex_mdm_copy_cli_certs_to_secondary
+ ansible.builtin.copy:
+ src: /tmp/cli_certificate.p12
+ dest: /opt/emc/scaleio/mdm/cfg/cli_certificate.p12
+ mode: preserve
+ delegate_to: "{{ powerflex_mdm_secondary_hostname }}"
+ when: powerflex_mdm_secondary_ip is defined
+
+- name: Copy mgmt_ca.pem certificates to Secondary manager MDM node
+ register: powerflex_mdm_copy_mgmt_certs_to_secondary
+ ansible.builtin.copy:
+ src: /tmp/mgmt_ca.pem
+ dest: /opt/emc/scaleio/mdm/cfg/mgmt_ca.pem
+ mode: preserve
+ delegate_to: "{{ powerflex_mdm_secondary_hostname }}"
+ when: powerflex_mdm_secondary_ip is defined
+
+- name: Copy MDM certificates to Tertiary manager MDM node
+ register: powerflex_mdm_copy_additional_certs_to_tertiary
+ ansible.builtin.copy:
+ src: /tmp/sec_mdm_certificate.pem
+ dest: /opt/emc/scaleio/mdm/cfg/mdm_certificate.pem
+ mode: preserve
+ delegate_to: "{{ powerflex_mdm_tertiary_hostname }}"
+ when: powerflex_mdm_tertiary_ip is defined
+
+- name: Copy CLI certificates to Tertiary manager MDM node
+ register: powerflex_mdm_copy_cli_certs_to_tertiary
+ ansible.builtin.copy:
+ src: /tmp/cli_certificate.p12
+ dest: /opt/emc/scaleio/mdm/cfg/cli_certificate.p12
+ mode: preserve
+ delegate_to: "{{ powerflex_mdm_tertiary_hostname }}"
+ when: powerflex_mdm_tertiary_ip is defined
+
+- name: Copy mgmt_ca.pem certificates to Tertiary manager MDM node
+ register: powerflex_mdm_copy_mgmt_certs_to_tertiary
+ ansible.builtin.copy:
+ src: /tmp/mgmt_ca.pem
+ dest: /opt/emc/scaleio/mdm/cfg/mgmt_ca.pem
+ mode: preserve
+ delegate_to: "{{ powerflex_mdm_tertiary_hostname }}"
+ when: powerflex_mdm_tertiary_ip is defined
+
+- name: Add CA certificate on primary MDM
+ register: powerflex_mdm_add_mgmt_cert_to_ca_primary
+ ansible.builtin.command: scli --add_certificate --certificate_file mgmt_ca.pem
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ args:
+ chdir: /opt/emc/scaleio/mdm/cfg
+ changed_when: powerflex_mdm_add_mgmt_cert_to_ca_primary.rc == 0
+
+- name: Add CA certificate on secondary MDM
+ register: powerflex_mdm_add_mgmt_cert_to_ca_secondary
+ ansible.builtin.command: scli --add_certificate --certificate_file mgmt_ca.pem
+ delegate_to: "{{ powerflex_mdm_secondary_hostname }}"
+ when: powerflex_mdm_secondary_ip is defined
+ args:
+ chdir: /opt/emc/scaleio/mdm/cfg
+ changed_when: powerflex_mdm_add_mgmt_cert_to_ca_secondary.rc == 0
+
+- name: Add CA certificate on tertiary MDM
+ register: powerflex_mdm_add_mgmt_cert_to_ca_tertiary
+ ansible.builtin.command: scli --add_certificate --certificate_file mgmt_ca.pem
+ delegate_to: "{{ powerflex_mdm_tertiary_hostname }}"
+ when: powerflex_mdm_tertiary_ip is defined
+ args:
+ chdir: /opt/emc/scaleio/mdm/cfg
+ changed_when: powerflex_mdm_add_mgmt_cert_to_ca_tertiary.rc == 0
+
+- name: Start MDM service on primary MDM
+ register: powerflex_mdm_start_service_primary
+ ansible.builtin.service:
+ name: "mdm.service"
+ state: "restarted"
+ enabled: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+
+- name: Start MDM service on secondary MDM
+ register: powerflex_mdm_start_service_secondary
+ ansible.builtin.service:
+ name: "mdm.service"
+ state: "restarted"
+ enabled: true
+ delegate_to: "{{ powerflex_mdm_secondary_hostname }}"
+ when: powerflex_mdm_secondary_ip is defined
+
+- name: Start MDM service on tertiary MDM
+ register: powerflex_mdm_start_service_tertiary
+ ansible.builtin.service:
+ name: "mdm.service"
+ state: "restarted"
+ enabled: true
+ delegate_to: "{{ powerflex_mdm_tertiary_hostname }}"
+ when: powerflex_mdm_tertiary_ip is defined
+
+- name: Check MDM service status
+ register: powerflex_mdm_check_service
+ ansible.builtin.command: systemctl status mdm.service
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ changed_when: powerflex_mdm_check_service.rc == 0
+
+- name: Delete certificates from localhost
+ register: powerflex_mdm_delete_localhost_certs
+ ansible.builtin.file:
+ path: /tmp/{{ item }}
+ state: absent
+ with_items:
+ - sec_mdm_certificate.pem
+ - cli_certificate.p12
+ - mgmt_ca.pem
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_mdm.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_mdm.yml
new file mode 100644
index 000000000..76bbba5a6
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_mdm.yml
@@ -0,0 +1,32 @@
+---
+- name: Include the mdm_set_facts.yml
+ ansible.builtin.include_tasks: "mdm_set_facts.yml"
+
+- name: Include vars
+ ansible.builtin.include_vars: "../vars/{{ ansible_distribution }}.yml"
+
+- name: Pre-requisite on rhel6 based os
+ ansible.posix.sysctl:
+ name: kernel.shmmax
+ value: 209715200
+ when: ansible_os_family == "RedHat" and ansible_distribution_major_version == "6"
+
+- name: List the rpm file
+ register: powerflex_mdm_package_file_version
+ ansible.builtin.find:
+ paths: "{{ powerflex_common_file_install_location }}"
+ patterns: "*{{ file_glob_name }}*.rpm"
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Extract file versions
+ ansible.builtin.set_fact:
+ version: "{{ powerflex_mdm_package_file_version.files[0].path | regex_search('mdm-(\\d+)', '\\1') }}"
+ when: powerflex_mdm_package_file_version.files | length > 0
+
+- name: Install MDM for PowerFlex below 4.x
+ ansible.builtin.include_tasks: install_powerflex3x_mdm.yml
+ when: version[0] < "4"
+
+- name: Install MDM for PowerFlex 4.x
+ ansible.builtin.include_tasks: install_powerflex4x_mdm.yml
+ when: version[0] >= "4"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex3x_mdm.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex3x_mdm.yml
new file mode 100644
index 000000000..178bd8696
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex3x_mdm.yml
@@ -0,0 +1,128 @@
+---
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Wait for MDM to be active
+ ansible.builtin.wait_for:
+ port: 9011
+ state: started
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+
+- name: Add primary MDM with virtual ip
+ ansible.builtin.command: >
+ scli --create_mdm_cluster
+ --master_mdm_ip {{ powerflex_mdm_primary_ip }}
+ --master_mdm_management_ip {{ powerflex_mdm_primary_ip }}
+ --master_mdm_name {{ powerflex_mdm_primary_hostname }}
+ --master_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --cluster_virtual_ip {{ powerflex_mdm_virtual_ip }}
+ --accept_license --approve_certificate
+ run_once: true
+ register: powerflex_mdm_add_primary_output
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ until: ("{{ powerflex_mdm_add_primary_output.rc }} == 0") or ("{{ powerflex_mdm_add_primary_output.rc }} == 7")
+ ignore_errors: true
+ when:
+ - powerflex_mdm_virtual_ip is defined
+ - powerflex_mdm_virtual_ip | length > 0
+ changed_when: powerflex_mdm_add_primary_output.rc == 0
+
+- name: Add primary MDM without virtual ip
+ ansible.builtin.command: >
+ scli --create_mdm_cluster
+ --master_mdm_ip {{ powerflex_mdm_primary_ip }}
+ --master_mdm_management_ip {{ powerflex_mdm_primary_ip }}
+ --master_mdm_name {{ powerflex_mdm_primary_hostname }}
+ --master_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --accept_license --approve_certificate
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ until: ("{{ powerflex_mdm_add_primary_output.rc }} == 0") or ("{{ powerflex_mdm_add_primary_output.rc }} == 7")
+ register: powerflex_mdm_add_primary_output
+ ignore_errors: true
+ when:
+ - powerflex_mdm_virtual_ip | length == 0
+ changed_when: powerflex_mdm_add_primary_output.rc == 0
+
+- name: Wait for MDM to be active
+ ansible.builtin.wait_for:
+ port: 6611
+ state: started
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+
+- name: Initial login to primary MDM
+ ansible.builtin.command: scli --login --username admin --password admin
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ ignore_errors: true
+ register: powerflex_mdm_initial_login
+ changed_when: powerflex_mdm_initial_login.rc == 0
+
+- name: Login with new password primary MDM
+ ansible.builtin.command: >
+ scli --login --username admin --password "{{ powerflex_mdm_password }}"
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ when: powerflex_mdm_initial_login.rc == 7
+ changed_when: powerflex_mdm_initial_login.rc == 0
+
+- name: Set password for MDM cluster
+ ansible.builtin.command: >
+ scli --set_password --old_password admin
+ --new_password "{{ powerflex_mdm_password }}"
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ when: powerflex_mdm_initial_login.rc == 0
+ changed_when: powerflex_mdm_initial_login.rc == 0
+
+- name: Secondary node login
+ ansible.builtin.command: >
+ scli --login --mdm_ip {{ powerflex_mdm_primary_ip }}
+ --username admin --password {{ powerflex_mdm_password }} --approve_certificate
+ run_once: true
+ register: powerflex_mdm_secondary_login
+ changed_when: powerflex_mdm_secondary_login.rc == 0
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+
+- name: Add secondary MDM
+ ansible.builtin.command: >
+ scli --add_standby_mdm
+ --new_mdm_ip {{ powerflex_mdm_secondary_ip }}
+ --mdm_role manager
+ --new_mdm_name {{ powerflex_mdm_secondary_hostname }}
+ --new_mdm_management_ip {{ powerflex_mdm_secondary_ip }}
+ --new_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --approve_certificate
+ run_once: true
+ register: powerflex_mdm_add_secondary_output
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ ignore_errors: true
+ changed_when: powerflex_mdm_add_secondary_output.rc == 0
+
+- name: Tertiary node login
+ ansible.builtin.command: >
+ scli --login --mdm_ip {{ powerflex_mdm_primary_ip }} --username admin
+ --password {{ powerflex_mdm_password }} --approve_certificate
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_tertiary_hostname }}"
+ when: powerflex_mdm_tertiary_ip is defined
+ register: powerflex_mdm_tertiary_login
+ changed_when: powerflex_mdm_tertiary_login.rc == 0
+
+- name: Add tertiary MDM
+ ansible.builtin.command: >
+ scli --add_standby_mdm
+ --new_mdm_ip {{ powerflex_mdm_tertiary_ip }}
+ --mdm_role manager
+ --new_mdm_name {{ powerflex_mdm_tertiary_hostname }}
+ --new_mdm_management_ip {{ powerflex_mdm_tertiary_ip }}
+ --new_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --approve_certificate
+ run_once: true
+ register: powerflex_mdm_add_tertiary_output
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ ignore_errors: true
+ when: powerflex_mdm_tertiary_ip is defined
+ changed_when: powerflex_mdm_add_tertiary_output.rc == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex4x_mdm.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex4x_mdm.yml
new file mode 100644
index 000000000..67164337d
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/install_powerflex4x_mdm.yml
@@ -0,0 +1,101 @@
+---
+- name: Install java
+ ansible.builtin.include_tasks: "../../powerflex_common/tasks/install_java_{{ ansible_distribution }}.yml"
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Include the add_certs.yml
+ ansible.builtin.include_tasks: add_certs.yml
+
+- name: Add primary MDM with virtual ip
+ ansible.builtin.command: >
+ scli --create_mdm_cluster
+ --primary_mdm_ip {{ powerflex_mdm_primary_ip }}
+ --primary_mdm_management_ip {{ powerflex_mdm_primary_ip }}
+ --primary_mdm_name {{ powerflex_mdm_primary_hostname }}
+ --primary_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --cluster_virtual_ip {{ powerflex_mdm_virtual_ip }}
+ --accept_license --approve_certificate
+ run_once: true
+ register: powerflex_mdm_add_primary_output
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ until: ("{{ powerflex_mdm_add_primary_output.rc }} == 0") or ("{{ powerflex_mdm_add_primary_output.rc }} == 7")
+ ignore_errors: true
+ when:
+ - powerflex_mdm_virtual_ip is defined
+ - powerflex_mdm_virtual_ip | length > 0
+ changed_when: powerflex_mdm_add_primary_output.rc == 0
+
+- name: Add primary MDM without virtual ip
+ ansible.builtin.command: >
+ scli --create_mdm_cluster
+ --primary_mdm_ip {{ powerflex_mdm_primary_ip }}
+ --primary_mdm_management_ip {{ powerflex_mdm_primary_ip }}
+ --primary_mdm_name {{ powerflex_mdm_primary_hostname }}
+ --primary_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --accept_license --approve_certificate
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ until: ("{{ powerflex_mdm_add_primary_output.rc }} == 0") or ("{{ powerflex_mdm_add_primary_output.rc }} == 7")
+ register: powerflex_mdm_add_primary_output
+ ignore_errors: true
+ when:
+ - powerflex_mdm_virtual_ip | length == 0
+ changed_when: powerflex_mdm_add_primary_output.rc == 0
+
+- name: Wait for MDM to be active
+ ansible.builtin.wait_for:
+ port: 8611
+ state: started
+ run_once: true
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+
+- name: Login to primary MDM node
+ register: powerflex_mdm_secondary_login
+ ansible.builtin.command: >
+ scli --login --p12_path /opt/emc/scaleio/mdm/cfg/cli_certificate.p12 --p12_password {{ powerflex_mdm_cert_password }}
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ run_once: true
+ when: powerflex_mdm_secondary_ip is defined
+ changed_when: powerflex_mdm_secondary_login.rc == 0
+
+- name: Add secondary MDM
+ ansible.builtin.command: >
+ scli --add_standby_mdm
+ --new_mdm_ip {{ powerflex_mdm_secondary_ip }}
+ --mdm_role manager
+ --new_mdm_name {{ powerflex_mdm_secondary_hostname }}
+ --new_mdm_management_ip {{ powerflex_mdm_secondary_ip }}
+ --new_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --approve_certificate
+ run_once: true
+ register: powerflex_mdm_add_secondary_output
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ ignore_errors: true
+ changed_when: powerflex_mdm_add_secondary_output.rc == 0
+
+- name: Login to Primary MDM node
+ register: powerflex_mdm_tertiary_login
+ ansible.builtin.command: >
+ scli --login --p12_path /opt/emc/scaleio/mdm/cfg/cli_certificate.p12 --p12_password {{ powerflex_mdm_cert_password }}
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ run_once: true
+ when: powerflex_mdm_tertiary_ip is defined
+ changed_when: powerflex_mdm_tertiary_login.rc == 0
+
+- name: Add tertiary MDM
+ ansible.builtin.command: >
+ scli --add_standby_mdm
+ --new_mdm_ip {{ powerflex_mdm_tertiary_ip }}
+ --mdm_role manager
+ --new_mdm_name {{ powerflex_mdm_tertiary_hostname }}
+ --new_mdm_management_ip {{ powerflex_mdm_tertiary_ip }}
+ --new_mdm_virtual_ip_interface {{ ansible_default_ipv4.interface }}
+ --approve_certificate
+ run_once: true
+ register: powerflex_mdm_add_tertiary_output
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ ignore_errors: true
+ when: powerflex_mdm_tertiary_ip is defined
+ changed_when: powerflex_mdm_add_tertiary_output.rc == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/main.yml
new file mode 100644
index 000000000..a5e2703ac
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Install and Configure MDM cluster
+ ansible.builtin.include_tasks: install_mdm.yml
+ when: powerflex_mdm_state == "present"
+
+- name: Uninstall MDM cluster
+ ansible.builtin.include_tasks: remove_mdm.yml
+ when: powerflex_mdm_state == "absent"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/mdm_set_facts.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/mdm_set_facts.yml
new file mode 100644
index 000000000..c24b889eb
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/mdm_set_facts.yml
@@ -0,0 +1,40 @@
+---
+- name: Set facts for MDM counts
+ ansible.builtin.set_fact:
+ mdm_count: "{{ groups['mdm'] | length }}"
+
+- name: Set facts for powerflex_mdm_primary_ip
+ ansible.builtin.set_fact:
+ powerflex_mdm_primary_ip: "{{ hostvars[groups['mdm'][0]]['ansible_host'] }}"
+
+- name: Set facts for powerflex_mdm_primary_hostname
+ ansible.builtin.set_fact:
+ powerflex_mdm_primary_hostname: "{{ hostvars[groups['mdm'][0]]['inventory_hostname'] }}"
+
+- name: Set facts for powerflex_mdm_secondary_ip
+ ansible.builtin.set_fact:
+ powerflex_mdm_secondary_ip: "{{ hostvars[groups['mdm'][1]]['ansible_host'] }}"
+
+- name: Set facts for powerflex_mdm_secondary_hostname
+ ansible.builtin.set_fact:
+ powerflex_mdm_secondary_hostname: "{{ hostvars[groups['mdm'][1]]['inventory_hostname'] }}"
+
+- name: Set facts for powerflex_mdm_tertiary_ip
+ ansible.builtin.set_fact:
+ powerflex_mdm_tertiary_ip: "{{ hostvars[groups['mdm'][2]]['ansible_host'] }}"
+ when: mdm_count | int > 2
+
+- name: Set facts for powerflex_mdm_tertiary_hostname
+ ansible.builtin.set_fact:
+ powerflex_mdm_tertiary_hostname: "{{ hostvars[groups['mdm'][2]]['inventory_hostname'] }}"
+ when: mdm_count | int > 2
+
+- name: Set facts for powerflex_mdm_ips if mdm_count is 2
+ ansible.builtin.set_fact:
+ powerflex_mdm_ips: "{{ powerflex_mdm_secondary_ip }},{{ powerflex_mdm_primary_ip }}"
+ when: mdm_count | int == 2
+
+- name: Set facts for powerflex_mdm_ips if mdm_count is more than 2
+ ansible.builtin.set_fact:
+ powerflex_mdm_ips: "{{ powerflex_mdm_secondary_ip }},{{ powerflex_mdm_primary_ip }},{{ powerflex_mdm_tertiary_ip }}"
+ when: mdm_count | int > 2
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/remove_mdm.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/remove_mdm.yml
new file mode 100644
index 000000000..5c200c5e3
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/remove_mdm.yml
@@ -0,0 +1,58 @@
+---
+- name: Include the mdm_set_facts.yml
+ ansible.builtin.include_tasks: mdm_set_facts.yml
+
+- name: List the rpm file
+ register: powerflex_mdm_package_file_version
+ ansible.builtin.find:
+ paths: "/var/tmp/"
+ patterns: "*{{ file_glob_name }}*.rpm"
+
+- name: Extract file versions
+ ansible.builtin.set_fact:
+ version: "{{ powerflex_mdm_package_file_version.files[0].path | regex_search('mdm-(\\d+)', '\\1') }}"
+ when: powerflex_mdm_package_file_version.files | length > 0
+
+- name: MDM Cluster login below PowerFlex 4.x
+ ansible.builtin.command: >
+ scli --login --mdm_ip {{ powerflex_mdm_primary_ip }}
+ --username admin --password {{ powerflex_mdm_password }} --approve_certificate
+ run_once: true
+ ignore_errors: true
+ register: powerflex_mdm_cluster_login
+ changed_when: powerflex_mdm_cluster_login.rc == 0
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ when: version[0] < "4"
+
+- name: Login to primary MDM node for PowerFlex 4.x
+ register: powerflex_mdm_primary_login
+ ansible.builtin.command: >
+ scli --login --username {{ username }} --management_system_ip {{ hostname }} --password "{{ password }}"
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ run_once: true
+ ignore_errors: true
+ changed_when: powerflex_mdm_primary_login.rc == 0
+ when: version[0] >= "4"
+
+- name: Remove secondary MDM
+ ansible.builtin.command: >
+ scli --remove_standby_mdm --remove_mdm_ip {{ powerflex_mdm_secondary_ip }}
+ run_once: true
+ register: powerflex_mdm_remove_secondary
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ ignore_errors: true
+ when: powerflex_mdm_secondary_ip is defined
+ changed_when: powerflex_mdm_remove_secondary.rc == 0
+
+- name: Remove tertiary MDM
+ ansible.builtin.command: >
+ scli --remove_standby_mdm --remove_mdm_ip {{ powerflex_mdm_tertiary_ip }}
+ run_once: true
+ register: powerflex_mdm_remove_tertiary
+ delegate_to: "{{ powerflex_mdm_primary_hostname }}"
+ ignore_errors: true
+ when: powerflex_mdm_tertiary_ip is defined
+ changed_when: powerflex_mdm_remove_tertiary.rc == 0
+
+- name: Include uninstall_mdm.yml
+ ansible.builtin.include_tasks: uninstall_mdm.yml
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/uninstall_mdm.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/uninstall_mdm.yml
new file mode 100644
index 000000000..a4302cb6d
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/tasks/uninstall_mdm.yml
@@ -0,0 +1,19 @@
+---
+- name: Uninstall MDM package
+ register: powerflex_mdm_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-mdm
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+- name: Uninstall deb package
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - emc-scaleio-mdm
+ when: ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/CentOS.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/CentOS.yml
new file mode 100644
index 000000000..1f3617cf0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/CentOS.yml
@@ -0,0 +1,5 @@
+---
+powerflex_mdm_packages:
+ - bash-completion
+ - python2
+ - binutils
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/RedHat.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/RedHat.yml
new file mode 100644
index 000000000..1f3617cf0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/RedHat.yml
@@ -0,0 +1,5 @@
+---
+powerflex_mdm_packages:
+ - bash-completion
+ - python2
+ - binutils
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/SLES.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/SLES.yml
new file mode 100644
index 000000000..f71b51d9a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/SLES.yml
@@ -0,0 +1,3 @@
+---
+powerflex_mdm_packages:
+ - python3
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/Ubuntu.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/Ubuntu.yml
new file mode 100644
index 000000000..3d64b947c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/Ubuntu.yml
@@ -0,0 +1,4 @@
+---
+powerflex_mdm_packages:
+ - bash-completion
+ - python2.7
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/main.yml
new file mode 100644
index 000000000..94678a3cf
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_mdm/vars/main.yml
@@ -0,0 +1,6 @@
+---
+file_glob_name: mdm
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_mdm_ips }}"
+ MDM_ROLE_IS_MANAGER: 1
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/README.md
new file mode 100644
index 000000000..5006cb6d4
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/README.md
@@ -0,0 +1,311 @@
+# powerflex_sdc
+
+Role to manage the installation and uninstallation of Powerflex SDC.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Notes](#notes)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+pywinrm==0.4.3
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+ansible.windows
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td>IP or FQDN of the PowerFlex gateway</td>
+ <td></td>
+ <td>str</td>
+ <td>10.1.1.1</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td>The username of the PowerFlex gateway</td>
+ <td></td>
+ <td>str</td>
+ <td>admin</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td>The password of the PowerFlex gateway</td>
+ <td></td>
+ <td>str</td>
+ <td>password</td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>false</td>
+ <td>Port</td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>If C(false), the SSL certificates will not be validated.<br>Configure C(false) only on personally controlled sites where self-signed certificates are used</td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>timeout</td>
+ <td>false</td>
+ <td>Timeout</td>
+ <td></td>
+ <td>int</td>
+ <td>120</td>
+ </tr>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>true</td>
+ <td>Location of installation and rpm gpg files to be installed.
+ <br>The required, compatible installation software package based on the operating system of the node.
+ <br>The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>str</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_common_win_package_location</td>
+ <td>false</td>
+ <td>Location of SDC windows package on the node.
+ <br>SDC windows package will be copied to this location on installation.</td>
+ <td></td>
+ <td>str</td>
+ <td>C:\\Windows\\Temp</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_repo_address</td>
+ <td>false</td>
+ <td>Repository address for the kernel modules</td>
+ <td></td>
+ <td>str</td>
+ <td>ftp://ftp.emc.com/</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_repo_user</td>
+ <td>false</td>
+ <td>Username for the repository</td>
+ <td></td>
+ <td>str</td>
+ <td>QNzgdxXix</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_repo_password</td>
+ <td>false</td>
+ <td>Password for the repository</td>
+ <td></td>
+ <td>str</td>
+ <td>Aw3wFAwAq3</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_repo_local_dir</td>
+ <td>false</td>
+ <td>Local cache of the repository</td>
+ <td></td>
+ <td>str</td>
+ <td>/bin/emc/scaleio/scini_sync/driver_cache/</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_user_private_rsa_key_src</td>
+ <td>false</td>
+ <td>Private ssh RSA key source (if using sftp protocol)</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_user_private_rsa_key_dest</td>
+ <td>false</td>
+ <td>Private ssh RSA key destination</td>
+ <td></td>
+ <td>str</td>
+ <td>/bin/emc/scaleio/scini_sync/scini_key</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_repo_public_rsa_key_src</td>
+ <td>false</td>
+ <td>Public ssh USA key source (if using sftp protocol)</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_repo_public_rsa_key_dest</td>
+ <td>false</td>
+ <td>Private ssh RSA key destination</td>
+ <td></td>
+ <td>str</td>
+ <td>/bin/emc/scaleio/scini_sync/scini_repo_key.pub</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_module_sigcheck</td>
+ <td>false</td>
+ <td>If signature check is required</td>
+ <td></td>
+ <td>str</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_emc_public_gpg_key_src</td>
+ <td>false</td>
+ <td>Location of the signature file</td>
+ <td></td>
+ <td>str</td>
+ <td>{{ powerflex_common_file_install_location }}/files/RPM-GPG-KEY-ScaleIO_2.0.*.0</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_emc_public_gpg_key_dest</td>
+ <td>false</td>
+ <td>Destination of the signature file</td>
+ <td></td>
+ <td>str</td>
+ <td>/bin/emc/scaleio/scini_sync/emc_key.pub</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_driver_sync_sync_pattern</td>
+ <td>false</td>
+ <td>Repo sync pattern</td>
+ <td></td>
+ <td>str</td>
+ <td>.*</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_name</td>
+ <td>false</td>
+ <td>Name of SDC to rename to<br></td>
+ <td></td>
+ <td>str</td>
+ <td>sdc_test</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_performance_profile</td>
+ <td>false</td>
+ <td>Performance profile of SDC<br></td>
+ <td></td>
+ <td>str</td>
+ <td>Compact</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_esxi_guid</td>
+ <td>false</td>
+ <td>Specifies the unique GUID for the ESXi SDC node.
+ <br>It is required only with ESXi node.
+ <br>To configure ESXi node as SDC, generate one GUID per server.
+ <br>Tools that are freely available online can generate these strings.
+ <br>If the value is different, then update in main.yml of defaults.</td>
+ <td></td>
+ <td>str</td>
+ <td>d422ecab-af6f-4e0c-a059-333ac89cfb42</td>
+ </tr>
+ <tr>
+ <td>powerflex_sdc_state</td>
+ <td>false</td>
+ <td>Specify state of SDC<br></td>
+ <td>absent, present</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Install and configure powerflex SDC
+ ansible.builtin.import_role:
+ name: powerflex_sdc
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_common_file_install_location: "/opt/scaleio/rpm"
+ powerflex_sdc_name: sdc_test
+ powerflex_sdc_performance_profile: Compact
+ powerflex_sdc_state: present
+
+ - name: Uninstall powerflex SDC
+ ansible.builtin.import_role:
+ name: powerflex_sdc
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_sdc_state: absent
+
+```
+
+## Notes
+- Generate GUID using https://www.guidgenerator.com/online-guid-generator.aspx. Use the default GUID settings.
+- While adding ESXi server as SDC, this procedure requires two server reboots.
+
+## Usage instructions
+----
+### To install all dependency packages, including SDC, on node:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+### To uninstall SDC:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Jennifer John (ansible.team@Dell.com) 2023 <br>
+Bhavneet Sharma (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/defaults/main.yml
new file mode 100644
index 000000000..5801c0ced
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/defaults/main.yml
@@ -0,0 +1,21 @@
+---
+powerflex_common_win_package_location: "C:\\Windows\\Temp"
+powerflex_sdc_driver_sync_repo_address: 'ftp://ftp.emc.com/'
+powerflex_sdc_driver_sync_repo_user: 'QNzgdxXix'
+powerflex_sdc_driver_sync_repo_password: 'Aw3wFAwAq3'
+powerflex_sdc_driver_sync_repo_local_dir: '/bin/emc/scaleio/scini_sync/driver_cache/'
+powerflex_sdc_driver_sync_user_private_rsa_key_src: ''
+powerflex_sdc_driver_sync_user_private_rsa_key_dest: '/bin/emc/scaleio/scini_sync/scini_key'
+powerflex_sdc_driver_sync_repo_public_rsa_key_src: ''
+powerflex_sdc_driver_sync_repo_public_rsa_key_dest: '/bin/emc/scaleio/scini_sync/scini_repo_key.pub'
+powerflex_sdc_driver_sync_module_sigcheck: 1
+powerflex_sdc_driver_sync_emc_public_gpg_key_src: ../../../files/RPM-GPG-KEY-powerflex_2.0.*.0
+powerflex_sdc_driver_sync_emc_public_gpg_key_dest: '/bin/emc/scaleio/scini_sync/emc_key.pub'
+powerflex_sdc_driver_sync_sync_pattern: .*
+powerflex_sdc_state: present
+powerflex_sdc_name: sdc_test
+powerflex_sdc_performance_profile: Compact
+file_glob_name: sdc
+i_am_sure: 1
+powerflex_sdc_esxi_guid: "d422ecab-af6f-4e0c-a059-333ac89cfb42"
+powerflex_role_environment:
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/handlers/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/handlers/main.yml
new file mode 100644
index 000000000..ecdcc3384
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: Restart scini
+ ansible.builtin.service:
+ name: "scini"
+ state: "restarted"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/meta/main.yml
new file mode 100644
index 000000000..2535678e4
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/meta/main.yml
@@ -0,0 +1,25 @@
+---
+galaxy_info:
+ author: Jennifer John
+ description: The role helps to manage the installation of SDC.
+ company: Dell Technologies
+ role_name: powerflex_sdc
+ namespace: dellemc
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.14.0"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/converge.yml
new file mode 100644
index 000000000..8f5049642
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/converge.yml
@@ -0,0 +1,118 @@
+---
+- name: Volume creation
+ hosts: localhost
+ vars_files:
+ - ../var_values.yml
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ tasks:
+ - name: Create a volume
+ dellemc.powerflex.volume:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ vol_name: "{{ vol_name }}"
+ storage_pool_name: "{{ storage_pool_name }}"
+ protection_domain_name: "{{ protection_domain_name }}"
+ size: "{{ vol_size }}"
+ state: "present"
+ register: volume_output
+
+- name: Install SDC
+ hosts: sdc
+ vars_files:
+ - ../var_values.yml
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ tasks:
+ - name: "Install and configure powerflex SDC"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_sdc_name: "{{ sdc_name }}"
+ powerflex_sdc_state: present
+ register: powerflex_sdc_result_molecule
+
+- name: Mapping SDC to volume
+ hosts: localhost
+ vars_files:
+ - ../var_values.yml
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: Map a SDC to volume
+ dellemc.powerflex.volume:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ vol_name: "{{ vol_name }}"
+ allow_multiple_mappings: true
+ sdc:
+ - sdc_name: "{{ sdc_name }}"
+ access_mode: "{{ access_mode }}"
+ sdc_state: "mapped"
+ state: "present"
+
+- name: Uninstall SDC
+ hosts: sdc
+ vars_files:
+ - ../var_values.yml
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: "Uninstall powerflex SDC"
+ register: powerflex_sdc_uninstall_outputs
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ ignore_errors: true
+ vars:
+ powerflex_sdc_name: "{{ sdc_name }}"
+ powerflex_sdc_state: 'absent'
+
+ - name: "Verifying failure of sdc removal"
+ ansible.builtin.assert:
+ that:
+ - "'SDC has mapped volume(s)' in powerflex_sdc_remove_output.msg"
+
+- name: Unmapping and Removing SDC
+ hosts: localhost
+ vars_files:
+ - ../var_values.yml
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: Unmap a SDC to volume
+ dellemc.powerflex.volume:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ vol_name: "{{ vol_name }}"
+ sdc:
+ - sdc_name: "{{ sdc_name }}"
+ sdc_state: "unmapped"
+ state: "present"
+
+ - name: Delete the Volume
+ dellemc.powerflex.volume:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ vol_name: "{{ vol_name }}"
+ delete_snapshots: false
+ state: "absent"
+
+ - name: Remove the SDC
+ dellemc.powerflex.sdc:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ sdc_name: "{{ sdc_name }}"
+ state: "absent"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/molecule.yml
new file mode 100644
index 000000000..93cad84c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_install_map_volume_uninstall_negative/molecule.yml
@@ -0,0 +1,4 @@
+---
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/converge.yml
new file mode 100644
index 000000000..4687e5ffc
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/converge.yml
@@ -0,0 +1,62 @@
+---
+- name: Converge
+ hosts: sdc
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: "Install and configure powerflex SDC"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_sdc_state: present
+ register: powerflex_sdc_result_molecule
+
+ - name: "Verifying installation package"
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when:
+ - not ansible_check_mode and powerflex_common_install_package_output.changed
+ - " 'WindowsOS' not in ansible_distribution "
+ - " 'VMkernel' not in ansible_distribution "
+
+ - name: "Verifying installation package on windows"
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_install_package_output.rc == 0
+ when:
+ - " 'WindowsOS' in ansible_distribution "
+ - not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: "Verifying installation package on ESXi"
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_install_package_output.rc == 0
+ when:
+ - " 'VMkernel' in ansible_distribution "
+ - not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: "Verifying performance profile value"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_performance_profile_output.sdc_details.perfProfile == "{{ powerflex_sdc_performance_profile }}"
+ when: not ansible_check_mode and powerflex_sdc_performance_profile_output.changed
+
+ - name: "Verifying rename value"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_rename_output.sdc_details.name == "{{ powerflex_sdc_name }}"
+ when: not ansible_check_mode and powerflex_sdc_performance_profile_output.changed
+
+ - name: "Verifying performance profile value in Idempotency"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_performance_profile_output.sdc_details.perfProfile == "{{ powerflex_sdc_performance_profile }}"
+ when: not ansible_check_mode and not powerflex_sdc_performance_profile_output.changed
+
+ - name: "Verifying rename value in Idempotency"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_rename_output.sdc_details.name == '{{ powerflex_sdc_name }}'
+ when: not ansible_check_mode and not powerflex_sdc_performance_profile_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/converge.yml
new file mode 100644
index 000000000..bb06afe18
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/converge.yml
@@ -0,0 +1,54 @@
+---
+- name: Converge
+ hosts: sdc
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: "Install and configure powerflex SDC with no rpm"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_common_file_install_location: "/opt/empty"
+ powerflex_sdc_state: present
+ register: powerflex_sdc_result_molecule
+ ignore_errors: true
+
+ - name: "Verifying failure of install package with respect to no rpm file"
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length == 0
+
+ - name: "Install and configure powerflex SDC with wrong file path"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_common_file_install_location: "/opt/aaab"
+ powerflex_sdc_state: present
+ register: powerflex_sdc_result_molecule
+ ignore_errors: true
+
+ - name: "Verifying failure of install package with wrong file path"
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length == 0
+
+ - name: "Install and configure powerflex SDC with wrong rpm version"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_common_file_install_location: "/opt/wrong_rpm"
+ powerflex_sdc_state: present
+ ignore_errors: true
+ register: powerflex_sdc_wrong_rpm_version
+
+ - name: "Verifying failure of install package with wrong rpm version"
+ ansible.builtin.assert:
+ that:
+ - " 'Depsolve Error occurred: ' in powerflex_common_install_package_output.msg"
+
+ - name: "Uninstall powerflex SDC"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_sdc_state: absent
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/molecule.yml
new file mode 100644
index 000000000..93cad84c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_installation_invalid_path_rpm/molecule.yml
@@ -0,0 +1,4 @@
+---
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/converge.yml
new file mode 100644
index 000000000..a11ce0ec4
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/converge.yml
@@ -0,0 +1,57 @@
+---
+- name: Converge
+ hosts: sdc
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: "Uninstall powerflex SDC"
+ register: powerflex_sdc_uninstall_outputs
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_sdc_state: 'absent'
+
+ - name: "Verifying uninstall package in check mode"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_uninstall_output.msg == "Check mode: No changes made, but would have if not in check mode"
+ - powerflex_sdc_uninstall_output.changed is true
+ when: ansible_check_mode
+
+ - name: "Verifying remove the sdc"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_remove_output.sdc_details is none
+ when: not ansible_check_mode and powerflex_sdc_remove_output.changed
+
+ - name: "Verifying uninstall package in Idempotency"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_uninstall_output.results[0].msg == 'Nothing to do'
+ when:
+ - not ansible_check_mode and not powerflex_sdc_uninstall_output.changed
+ - " 'WindowsOS' not in ansible_distribution "
+ - " 'VMkernel' not in ansible_distribution "
+
+ - name: "Verifying uninstall package in Idempotency for Windows node"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_uninstall_output.msg == 'All items skipped'
+ when:
+ - not ansible_check_mode and not powerflex_sdc_uninstall_output.changed
+ - " 'WindowsOS' in ansible_distribution "
+
+ - name: "Verifying uninstall package in Idempotency for ESXi node"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_uninstall_output.msg == 'All items skipped'
+ when:
+ - not ansible_check_mode and not powerflex_sdc_uninstall_output.changed
+ - " 'VMkernel' in ansible_distribution "
+
+ - name: "Verifying remove the sdc in Idempotency"
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdc_remove_output.sdc_details is none
+ when: not ansible_check_mode and not powerflex_sdc_remove_output.changed and powerflex_sdc_remove_output.sdc_details is defined
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/sdc_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/var_values.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/var_values.yml
new file mode 100644
index 000000000..91e203e08
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/var_values.yml
@@ -0,0 +1,7 @@
+---
+vol_name: "sdc_test_vol_1"
+storage_pool_name: "pool1"
+protection_domain_name: "domain1"
+vol_size: 8
+sdc_name: sdc_test_demo_1
+access_mode: "READ_WRITE"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/converge.yml
new file mode 100644
index 000000000..86583fd34
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/converge.yml
@@ -0,0 +1,20 @@
+---
+- name: Converge
+ hosts: sdc
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: false
+ tasks:
+ - name: "Install and configure powerflex SDC with wrong credentials"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_sdc_state: present
+ ignore_unreachable: true
+ ignore_errors: true
+ register: powerflex_sdc_wrong_credentials_output
+
+ - name: "Verifying failure of install package with wrong credentials"
+ ansible.builtin.assert:
+ that:
+ - " 'failed. The error was: error while evaluating conditional' in powerflex_sdc_driver_sync_output.msg"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/inventory b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/inventory
new file mode 100644
index 000000000..1974d7ad4
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/inventory
@@ -0,0 +1,4 @@
+node0 ansible_host=10.2.2.2 ansible_port=22 ansible_ssh_pass=wrongpassword ansible_user=root
+
+[sdc]
+node0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/molecule.yml
new file mode 100644
index 000000000..805f92879
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_credentials/molecule.yml
@@ -0,0 +1,11 @@
+---
+provisioner:
+ name: ansible
+ inventory:
+ links:
+ hosts: inventory
+ group_vars: ../../../../playbooks/roles/group_vars/
+ host_vars: ../../../../playbooks/roles/host_vars/
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/converge.yml
new file mode 100644
index 000000000..1ebda8c05
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/converge.yml
@@ -0,0 +1,20 @@
+---
+- name: Converge
+ hosts: sdc
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: false
+ tasks:
+ - name: "Install and configure powerflex SDC with wrong SDC IP"
+ ansible.builtin.import_role:
+ name: "powerflex_sdc"
+ vars:
+ powerflex_sdc_state: present
+ ignore_unreachable: true
+ ignore_errors: true
+ register: powerflex_sdc_wrong_ip_output
+
+ - name: "Verifying failure of install package with wrong SDC IP"
+ ansible.builtin.assert:
+ that:
+ " 'failed. The error was: error while evaluating conditional' in powerflex_sdc_driver_sync_output.msg"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/inventory b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/inventory
new file mode 100644
index 000000000..845add1d5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/inventory
@@ -0,0 +1,4 @@
+node0 ansible_host=10.2.2.0 ansible_port=22 ansible_ssh_pass=password ansible_user=root
+
+[sdc]
+node0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/molecule.yml
new file mode 100644
index 000000000..805f92879
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/molecule/wrong_sdc_ip/molecule.yml
@@ -0,0 +1,11 @@
+---
+provisioner:
+ name: ansible
+ inventory:
+ links:
+ hosts: inventory
+ group_vars: ../../../../playbooks/roles/group_vars/
+ host_vars: ../../../../playbooks/roles/host_vars/
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/configure_sdc.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/configure_sdc.yml
new file mode 100644
index 000000000..453fe43d5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/configure_sdc.yml
@@ -0,0 +1,28 @@
+---
+- name: Rename the SDC
+ dellemc.powerflex.sdc:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ sdc_ip: "{{ ansible_host }}"
+ sdc_new_name: "{{ powerflex_sdc_name }}"
+ state: "present"
+ register: powerflex_sdc_rename_output
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+ when: powerflex_sdc_name is defined and powerflex_sdc_name | length > 0
+
+- name: Set performance profile of SDC
+ dellemc.powerflex.sdc:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ sdc_ip: "{{ ansible_host }}"
+ performance_profile: "{{ powerflex_sdc_performance_profile }}"
+ state: "present"
+ register: powerflex_sdc_performance_profile_output
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+ when:
+ - powerflex_sdc_performance_profile is defined
+ - powerflex_sdc_performance_profile | length > 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/install_sdc.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/install_sdc.yml
new file mode 100644
index 000000000..9b75321c3
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/install_sdc.yml
@@ -0,0 +1,75 @@
+---
+- name: Get configured MDM IP addresses
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ state: "present"
+ register: powerflex_sdc_mdm_ip_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Set fact - powerflex_sdc_mdm_ips
+ ansible.builtin.set_fact:
+ powerflex_sdc_mdm_ips: "{{ powerflex_sdc_mdm_ip_result.mdm_cluster_details.mdmAddresses | join(',') }}"
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Register SDC and Set MDM IP addresses by register_esxi_sdc.yml
+ ansible.builtin.include_tasks: register_esxi_sdc.yml
+ when: ansible_distribution == "VMkernel"
+
+- name: Include configure_sdc.yml
+ ansible.builtin.include_tasks: configure_sdc.yml
+
+- name: Copy powerflex_sdc_driver_sync_user_private_rsa_key_src for driver_sync.conf
+ ansible.builtin.copy:
+ src: "{{ powerflex_sdc_driver_sync_user_private_rsa_key_src }}"
+ dest: "{{ powerflex_sdc_driver_sync_user_private_rsa_key_dest }}"
+ mode: "0600"
+ owner: "root"
+ group: "root"
+ when:
+ - powerflex_sdc_driver_sync_user_private_rsa_key_src is defined
+ - powerflex_sdc_driver_sync_user_private_rsa_key_src | length > 0
+ - " 'WindowsOS' not in ansible_distribution"
+
+- name: Copy powerflex_sdc_driver_sync_repo_public_rsa_key_src for driver_sync.conf
+ ansible.builtin.copy:
+ src: "{{ powerflex_sdc_driver_sync_repo_public_rsa_key_src }}"
+ dest: "{{ powerflex_sdc_driver_sync_repo_public_rsa_key_dest }}"
+ mode: "0600"
+ owner: "root"
+ group: "root"
+ when:
+ - powerflex_sdc_driver_sync_repo_public_rsa_key_src is defined
+ - powerflex_sdc_driver_sync_repo_public_rsa_key_src | length > 0
+ - " 'WindowsOS' not in ansible_distribution"
+
+- name: Copy powerflex_sdc_driver_sync_emc_public_gpg_key_src for driver_sync.conf
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "{{ powerflex_sdc_driver_sync_emc_public_gpg_key_dest }}"
+ mode: "0600"
+ owner: "root"
+ group: "root"
+ with_fileglob:
+ - "{{ powerflex_sdc_driver_sync_emc_public_gpg_key_src }}"
+ when:
+ - powerflex_sdc_driver_sync_emc_public_gpg_key_src is defined
+ - powerflex_sdc_driver_sync_emc_public_gpg_key_src | length > 0
+ - " 'WindowsOS' not in ansible_distribution"
+
+- name: Copy driver_sync.conf template in place
+ register: powerflex_sdc_driver_sync_output
+ ansible.builtin.template:
+ src: "driver_sync.conf.j2"
+ dest: "/bin/emc/scaleio/scini_sync/driver_sync.conf"
+ mode: "0600"
+ owner: "root"
+ group: "root"
+ notify: restart scini
+ when:
+ - ansible_distribution != "VMkernel"
+ - " 'WindowsOS' not in ansible_distribution"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/main.yml
new file mode 100644
index 000000000..ec81fb21f
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Install SDC
+ ansible.builtin.include_tasks: install_sdc.yml
+ when: powerflex_sdc_state == 'present'
+
+- name: Remove SDC
+ ansible.builtin.include_tasks: remove_sdc.yml
+ when: powerflex_sdc_state == 'absent'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/register_esxi_sdc.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/register_esxi_sdc.yml
new file mode 100644
index 000000000..0b06fc8cd
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/register_esxi_sdc.yml
@@ -0,0 +1,47 @@
+---
+- name: Register SDC and Set MDM IP addresses
+ register: powerflex_sdc_register_set_sdc_mdm
+ ansible.builtin.shell: >
+ esxcli system module parameters set -m scini -p "IoctlIniGuidStr={{ powerflex_sdc_esxi_guid }}
+ IoctlMdmIPStr={{ powerflex_sdc_mdm_ips }} bBlkDevIsPdlActive=1 blkDevPdlTimeoutMillis=60000"
+ changed_when: powerflex_sdc_register_set_sdc_mdm.rc == 0
+
+- name: Reboot ESXi host
+ register: powerflex_sdc_reboot_node
+ ansible.builtin.reboot:
+ reboot_timeout: 500
+ msg: "Rebooting the ESXi host."
+ when:
+ - powerflex_sdc_register_set_sdc_mdm.rc == 0
+ - "'Reboot Required: true' in powerflex_common_install_package_output.stdout"
+ changed_when: powerflex_sdc_reboot_node
+
+- name: Ensure the driver is loaded for SDC
+ register: powerflex_sdc_driver_loaded
+ ansible.builtin.shell: >
+ set -o pipefail && vmkload_mod -l | grep scini
+ changed_when: powerflex_sdc_driver_loaded.stdout_lines | length == 0
+
+- name: Verify ESXi SDC connection with MDMs
+ ansible.builtin.copy:
+ src: "{{ item }}"
+ dest: "{{ powerflex_common_esxi_files_location }}"
+ mode: "0755"
+ register: powerflex_sdc_drv_cfg_file_output
+ with_fileglob:
+ - "{{ powerflex_common_file_install_location }}/drv_cfg*"
+
+- name: List the drv_cfg file
+ register: powerflex_sdc_drv_cfg_file
+ ansible.builtin.find:
+ paths: "{{ powerflex_common_esxi_files_location }}"
+ patterns: "*drv_cfg*"
+
+- name: Execute drv_cfg command
+ register: powerflex_sdc_drv_cfg_output
+ ansible.builtin.command: ./drv_cfg --query_mdm
+ args:
+ chdir: "{{ powerflex_common_esxi_files_location }}"
+ when: powerflex_sdc_drv_cfg_file.files | length > 0
+ changed_when:
+ - "'Retrieved 1 mdm(s)' not in powerflex_sdc_drv_cfg_output.stdout"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/remove_sdc.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/remove_sdc.yml
new file mode 100644
index 000000000..b8e9b5492
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/remove_sdc.yml
@@ -0,0 +1,20 @@
+---
+- name: Set fact # noqa var-naming[no-role-prefix]
+ ansible.builtin.set_fact:
+ ansible_distribution: "WindowsOS"
+ when: " 'Windows' in ansible_distribution"
+
+- name: Include uninstall_sdc.yml
+ ansible.builtin.include_tasks: uninstall_sdc.yml
+
+- name: Remove the SDC
+ dellemc.powerflex.sdc:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ sdc_name: "{{ powerflex_sdc_name }}"
+ state: "absent"
+ register: powerflex_sdc_remove_output
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+ when: powerflex_sdc_name is defined and powerflex_sdc_name | length > 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_esxi_sdc.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_esxi_sdc.yml
new file mode 100644
index 000000000..b3c3c68df
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_esxi_sdc.yml
@@ -0,0 +1,30 @@
+---
+- name: Get the name of SDC driver installed
+ register: powerflex_sdc_installed_driver_list
+ ansible.builtin.shell: >
+ set -o pipefail && esxcli software vib list | grep sdc
+ changed_when: powerflex_sdc_installed_driver_list.stdout_lines | length == 0
+ ignore_errors: true
+
+- name: Remove the SDC driver form the esxi host
+ register: powerflex_sdc_remove_driver_output
+ ansible.builtin.shell: >
+ esxcli software vib remove -n {{ powerflex_sdc_installed_driver_list.stdout.split()[0] }}
+ changed_when: "'Reboot Required: true' in powerflex_sdc_remove_driver_output.stdout"
+ when: powerflex_sdc_installed_driver_list.stdout_lines | length != 0
+
+- name: Reboot ESXi host
+ register: powerflex_sdc_remove_driver_reboot_output
+ ansible.builtin.reboot:
+ reboot_timeout: 450
+ msg: "Rebooting the ESXi host."
+ when:
+ - powerflex_sdc_installed_driver_list.stdout_lines | length != 0
+ changed_when: powerflex_sdc_remove_driver_reboot_output.rebooted
+
+- name: List the SDC driver installed
+ ansible.builtin.shell: >
+ set -o pipefail && esxcli software vib list | grep sdc
+ register: powerflex_sdc_drivers_list
+ changed_when: powerflex_sdc_drivers_list.stdout_lines | length != 0
+ failed_when: powerflex_sdc_drivers_list.stdout_lines | length != 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_sdc.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_sdc.yml
new file mode 100644
index 000000000..e46a32683
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/tasks/uninstall_sdc.yml
@@ -0,0 +1,40 @@
+---
+- name: Uninstall package
+ register: powerflex_sdc_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-sdc
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES", "Rocky")
+
+- name: Uninstall deb package
+ register: powerflex_sdc_uninstall_deb_output
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - emc-scaleio-sdc
+ when: ansible_distribution == "Ubuntu"
+
+- name: Include uninstall_esxi_sdc.yml to uninstall the esxi sdc
+ ansible.builtin.include_tasks: uninstall_esxi_sdc.yml
+ when: ansible_distribution == "VMkernel"
+
+- name: List the msi files
+ ansible.windows.win_find:
+ paths: "{{ powerflex_common_win_package_location }}"
+ patterns: "*{{ file_glob_name }}*.msi"
+ register: powerflex_sdc_msi_package_files
+ when: ansible_distribution == "WindowsOS"
+
+- name: Uninstall win package
+ register: powerflex_sdc_uninstall_win_output
+ ansible.windows.win_package:
+ path: "{{ item.path }}"
+ state: absent
+ with_items:
+ - "{{ powerflex_sdc_msi_package_files.files }}"
+ when: ansible_distribution == "WindowsOS"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/templates/driver_sync.conf.j2 b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/templates/driver_sync.conf.j2
new file mode 100644
index 000000000..08541128e
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/templates/driver_sync.conf.j2
@@ -0,0 +1,31 @@
+###############################################################################
+# driver_sync Configuration file
+# Everything after a '#' until the end of the line is ignored
+###############################################################################
+
+# Repository address, prefixed by protocol
+repo_address = {{ powerflex_sdc_driver_sync_repo_address }}
+
+# Repository user (valid for ftp/sftp protocol)
+repo_user = {{ powerflex_sdc_driver_sync_repo_user }}
+
+# Repository password (valid for ftp protocol)
+repo_password = {{ powerflex_sdc_driver_sync_repo_password }}
+
+# Local directory for modules
+local_dir = {{ powerflex_sdc_driver_sync_repo_local_dir }}
+
+# User's RSA private key file (sftp protocol)
+user_private_rsa_key = {{ powerflex_sdc_driver_sync_user_private_rsa_key_dest }}
+
+# Repository host public key (sftp protocol)
+repo_public_rsa_key = {{ powerflex_sdc_driver_sync_repo_public_rsa_key_dest }}
+
+# Should the fetched modules' signatures be checked [0, 1]
+module_sigcheck = {{ powerflex_sdc_driver_sync_module_sigcheck }}
+
+# EMC public signature key (needed when module_sigcheck is 1)
+emc_public_gpg_key = {{ powerflex_sdc_driver_sync_emc_public_gpg_key_dest }}
+
+# Sync pattern (regular expression) for massive retrieve
+sync_pattern = {{ powerflex_sdc_driver_sync_sync_pattern }}
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/vars/main.yml
new file mode 100644
index 000000000..ad6c0e4e2
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdc/vars/main.yml
@@ -0,0 +1,5 @@
+---
+file_glob_name: sdc
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_sdc_mdm_ips }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/README.md
new file mode 100644
index 000000000..e83491329
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/README.md
@@ -0,0 +1,145 @@
+# powerflex_sdr
+
+Role to manage installation and uninstallation PowerFlex SDR.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>false</td>
+ <td>Location of required, compatible installation software package based on the operating system of the node.
+ <br>The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>path</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_protection_domain_name</td>
+ <td>false</td>
+ <td>The name of the protection domain to which the SDR will be added.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_storage_pool_name</td>
+ <td>false</td>
+ <td>The name of the storage pool to which the device will be added.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sdr_repl_journal_capacity_max_ratio</td>
+ <td>false</td>
+ <td>Maximum capacity percentage to be allocated for journal capacity. Range is 0 to 100.</td>
+ <td></td>
+ <td>int</td>
+ <td>10</td>
+ </tr>
+ <tr>
+ <td>powerflex_mdm_password</td>
+ <td>true</td>
+ <td>Password for primary MDM node.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+<tr>
+ <td>powerflex_sdr_state</td>
+ <td>false</td>
+ <td>State of the SDR.</td>
+ <td>present, absent</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Install powerflex SDR
+ ansible.builtin.include_role:
+ name: powerflex_sdr
+ vars:
+ powerflex_protection_domain_name: domain1
+ powerflex_storage_pool_name: pool1
+ powerflex_sdr_repl_journal_capacity_max_ratio: 10
+ powerflex_sdr_state: present
+ powerflex_mdm_password: Password111
+
+ - name: Uninstall powerflex SDR
+ ansible.builtin.include_role:
+ name: powerflex_sdr
+ vars:
+ powerflex_mdm_password: Password111
+ powerflex_sdr_state: absent
+
+```
+
+## Usage instructions
+----
+### To install all dependency packages, including SDR, on node:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+### To uninstall SDR:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Abhishek Sinha (ansible.team@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/defaults/main.yml
new file mode 100644
index 000000000..efae8a870
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+# defaults file for powerflex_sdr
+file_glob_name: sdr
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_common_file_install_location: "/var/tmp"
+powerflex_sdr_repl_journal_capacity_max_ratio: 10
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_sdr_mdm_primary_ip }}"
+powerflex_sdr_state: present
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/argument_specs.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/argument_specs.yml
new file mode 100644
index 000000000..b730ebed4
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/argument_specs.yml
@@ -0,0 +1,34 @@
+---
+argument_specs:
+ main:
+ short_description: Role to manage installation and uninstallation Powerflex SDR
+ description:
+ - Role to manage installation and uninstallation Powerflex SDR.
+ options:
+ powerflex_common_file_install_location:
+ description:
+ - Location of installation and rpm gpg files to be installed.
+ - The required, compatible installation software package based on the operating system of the node.
+ - The files can be downloaded from the Dell Product support page for PowerFlex software.
+ type: path
+ default: /var/tmp
+ powerflex_sdr_state:
+ description:
+ - Specifies the state of SDR.
+ type: str
+ choices: ['absent', 'present']
+ default: present
+ powerflex_protection_domain_name:
+ description: The name of the protection domain to which the SDR will be added.
+ type: str
+ powerflex_storage_pool_name:
+ description: The name of the storage pool to which the device will be added.
+ type: str
+ powerflex_sdr_repl_journal_capacity_max_ratio:
+ description: Maximum capacity percentage to be allocated for journal capacity.
+ type: int
+ default: 10
+ powerflex_mdm_password:
+ required: true
+ type: str
+ description: Password for the Powerflex MDM.
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/main.yml
new file mode 100644
index 000000000..e0280962c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/meta/main.yml
@@ -0,0 +1,21 @@
+---
+galaxy_info:
+ role_name: powerflex_sdr
+ namespace: dellemc
+ author: Abhishek Sinha
+ description: The role to manage installation and uninstallation PowerFlex SDR.
+ company: Dell Technologies
+ license: GPL-3.0-only
+ min_ansible_version: "2.14.0"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/converge.yml
new file mode 100644
index 000000000..3e4bb51fa
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/converge.yml
@@ -0,0 +1,30 @@
+---
+- name: Molecule Test for installation of SDR
+ hosts: sdr
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Install and configure Powerflex SDR
+ ansible.builtin.import_role:
+ name: powerflex_sdr
+ vars:
+ powerflex_sdr_state: present
+
+ - name: Verifying install package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_install_package_output.msg == "Check mode: No changes made"
+ when: ansible_check_mode
+
+ - name: Verifying installation package in normal mode
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: Verifying installation package in Idempotency mode
+ ansible.builtin.assert:
+ that:
+ - "'Nothing to do' in powerflex_common_install_package_output.msg"
+ when: not ansible_check_mode and not powerflex_common_install_package_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/converge.yml
new file mode 100644
index 000000000..bc5b5d3d5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/converge.yml
@@ -0,0 +1,34 @@
+---
+- name: Molecule Test for installation of SDR with invalid rpm path, rpm file
+ hosts: sdr
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Install and configure powerflex SDR with no rpm
+ ansible.builtin.import_role:
+ name: powerflex_sdr
+ vars:
+ powerflex_common_file_install_location: "/opt/empty"
+ powerflex_sdr_state: present
+ register: powerflex_sdr_no_rpm_result
+ ignore_errors: true
+
+ - name: Verifying failure of install package with respect to no rpm file in normal mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length | int == 0
+
+ - name: Install and configure powerflex SDR with wrong file path
+ ansible.builtin.import_role:
+ name: powerflex_sdr
+ vars:
+ powerflex_common_file_install_location: "/opt/aaab"
+ powerflex_sdr_state: present
+ ignore_errors: true
+ register: powerflex_sdr_wrong_path_result
+
+ - name: Verifying failure of install package with wrong file path
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/molecule.yml
new file mode 100644
index 000000000..93cad84c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_path_rpm/molecule.yml
@@ -0,0 +1,4 @@
+---
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/converge.yml
new file mode 100644
index 000000000..17a448963
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/converge.yml
@@ -0,0 +1,20 @@
+---
+- name: Molecule Test for installation of SDR
+ hosts: sdr
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Install and configure powerflex SDR without protection domain
+ vars:
+ error_msg: "Please provide powerflex_protection_domain_name and powerflex_storage_pool_name in parameter for installing SDR."
+ block:
+ - name: Powerflex SDR
+ ansible.builtin.import_role:
+ name: dellemc.powerflex.powerflex_sdr
+ vars:
+ powerflex_sdr_state: present
+ rescue:
+ - name: Verifying failure of install package without protection domain
+ ansible.builtin.assert:
+ that: ansible_failed_result.ansible_facts.powerflex_add_sdr_output.msg == error_msg
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/molecule.yml
new file mode 100644
index 000000000..93cad84c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_installation_invalid_pd/molecule.yml
@@ -0,0 +1,4 @@
+---
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/converge.yml
new file mode 100644
index 000000000..cc28cae33
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/converge.yml
@@ -0,0 +1,66 @@
+---
+- name: SDR uninstallation
+ hosts: sdr
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+
+ tasks:
+ - name: Uninstall powerflex SDR
+ register: powerflex_sdr_uninstall_outputs
+ ansible.builtin.import_role:
+ name: powerflex_sdr
+ vars:
+ powerflex_sdr_state: absent
+
+ - name: Verifying uninstall package in converge
+ ansible.builtin.assert:
+ that:
+ - " 'Removed:' in powerflex_sdr_uninstall_output.results[0].results[0]"
+ when:
+ - not ansible_check_mode
+ - powerflex_sdr_uninstall_output.changed
+ - ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdr_uninstall_output.msg == "Check mode: No changes made"
+ - powerflex_sdr_uninstall_output.changed
+ - ansible_distribution in ("RedHat", "CentOS", "SLES")
+ when: ansible_check_mode
+
+ - name: Verifying remove the sdr in normal mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_remove_sdr_output.sdr_details is None
+ when:
+ - not ansible_check_mode
+ - powerflex_remove_sdr_output.changed
+ - ansible_distribution == "Ubuntu"
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_sdr_uninstall_output.results[0].msg == 'Nothing to do'
+ - ansible_distribution in ("RedHat", "CentOS", "SLES")
+ when:
+ - not ansible_check_mode
+ - not powerflex_sdr_uninstall_output.changed
+ - ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying remove the sdr in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_remove_sdr_output.msg == "Check mode: No changes made"
+ - powerflex_remove_sdr_output.changed
+ - ansible_distribution == "Ubuntu"
+ when: ansible_check_mode
+
+ - name: Verifying remove the sdr in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_remove_sdr_output.sdr_details is None
+ when:
+ - not ansible_check_mode
+ - not powerflex_remove_sdr_output.changed
+ - ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/sdr_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/var_values.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/var_values.yml
new file mode 100644
index 000000000..87df25556
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/molecule/var_values.yml
@@ -0,0 +1,3 @@
+---
+powerflex_protection_domain_name: domain1
+powerflex_storage_pool_name: pool1
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/add_sdr.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/add_sdr.yml
new file mode 100644
index 000000000..1af345276
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/add_sdr.yml
@@ -0,0 +1,142 @@
+---
+- name: Get configured MDM IP addresses
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ state: "present"
+ register: powerflex_sdr_mdm_ip_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Set fact - PowerFlex version
+ ansible.builtin.set_fact:
+ powerflex_sdr_array_version: "{{ powerflex_sdr_mdm_ip_result.mdm_cluster_details.master.versionInfo[1] }}"
+
+- name: Checking powerflex_protection_domain_name and powerflex_storage_pool_name is provided
+ ansible.builtin.set_fact:
+ powerflex_add_sdr_output:
+ msg: Please provide powerflex_protection_domain_name and powerflex_storage_pool_name in parameter for installing SDR.
+ failed_when:
+ - powerflex_protection_domain_name is undefined or powerflex_storage_pool_name is undefined
+
+- name: Include the sdr_set_facts.yml
+ ansible.builtin.include_tasks: sdr_set_facts.yml
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Login to mdm for PowerFlex version below 4.x
+ ansible.builtin.command: >
+ scli --login --mdm_ip {{ powerflex_sdr_mdm_primary_ip }}
+ --username admin
+ --password "{{ powerflex_mdm_password }}"
+ --approve_certificate
+ run_once: true
+ register: powerflex_initial_login
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_initial_login.rc == 0
+ no_log: true
+ when: powerflex_sdr_array_version == "3"
+
+- name: Login to mdm for PowerFlex version 4.x
+ ansible.builtin.command: >
+ scli --login --management_system_ip {{ hostname }}
+ --username admin
+ --password "{{ password }}"
+ --approve_certificate
+ run_once: true
+ register: powerflex_initial_login
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_initial_login.rc == 0
+ no_log: true
+ when: powerflex_sdr_array_version != "3"
+
+- name: Output msg of previous task login to mdm
+ ansible.builtin.debug:
+ var: powerflex_initial_login.stdout
+
+- name: Set replication capacity
+ ansible.builtin.command: >
+ scli --set_replication_journal_capacity
+ --protection_domain_name {{ powerflex_protection_domain_name }}
+ --storage_pool_name {{ powerflex_storage_pool_name }}
+ --replication_journal_capacity_max_ratio {{ powerflex_sdr_repl_journal_capacity_max_ratio }}
+ run_once: true
+ register: powerflex_set_replication_capacity
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_set_replication_capacity.rc == 0
+
+- name: Wait for replication capacity to be created
+ ansible.builtin.pause:
+ seconds: 60
+ run_once: true
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+
+- name: Get replication capacity
+ ansible.builtin.command: >
+ scli --query_all_replication_journal_capacity
+ --protection_domain_name {{ powerflex_protection_domain_name }}
+ run_once: true
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ register: powerflex_get_replication_capacity
+ changed_when: powerflex_get_replication_capacity.rc == 0
+
+- name: Checking if SDR already exists or not for PowerFlex version below 4.x
+ ansible.builtin.command: >
+ scli --mdm_ip {{ powerflex_sdr_mdm_primary_ip }}
+ --query_sdr
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ register: check_sdr_exists
+ changed_when: check_sdr_exists.rc == 0
+ failed_when: false
+ when: powerflex_sdr_array_version == "3"
+
+- name: Checking if SDR already exists or not for PowerFlex version 4.x
+ ansible.builtin.command: >
+ scli --management_system_ip {{ hostname }}
+ --query_sdr
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ register: check_sdr_exists
+ changed_when: check_sdr_exists.rc == 0
+ failed_when: false
+ when: powerflex_sdr_array_version != "3"
+
+- name: Skipping add SDR if already exists
+ ansible.builtin.debug:
+ msg: "SDR name {{ powerflex_sdr_hostname }} already exists, will skip adding SDR."
+ when: check_sdr_exists.rc == 0
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+
+- name: Adding SDR for PowerFlex version below 4.x
+ ansible.builtin.command: >
+ scli --add_sdr --mdm_ip {{ powerflex_sdr_mdm_primary_ip }}
+ --sdr_ip_role all
+ --sdr_ip {{ powerflex_sdr_ip }}
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ --protection_domain_name {{ powerflex_protection_domain_name }}
+ register: powerflex_add_sdr_output
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_add_sdr_output.rc == 0
+ when: check_sdr_exists.rc == 7 and powerflex_sdr_array_version == "3"
+
+- name: Adding SDR for PowerFlex version 4.x
+ ansible.builtin.command: >
+ scli --add_sdr --management_system_ip {{ hostname }}
+ --sdr_ip_role all
+ --sdr_ip {{ powerflex_sdr_ip }}
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ --protection_domain_name {{ powerflex_protection_domain_name }}
+ register: powerflex_add_sdr_output
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_add_sdr_output.rc == 0
+ when: check_sdr_exists.rc == 7 and powerflex_sdr_array_version != "3"
+
+- name: Logging out of the mdm
+ ansible.builtin.command: scli --logout
+ register: powerflex_mdm_logout
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_mdm_logout.rc == 0
+ run_once: true
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/main.yml
new file mode 100644
index 000000000..440173b8d
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Add SDR
+ ansible.builtin.include_tasks: add_sdr.yml
+ when: powerflex_sdr_state == 'present'
+
+- name: Remove SDR
+ ansible.builtin.include_tasks: remove_sdr.yml
+ when: powerflex_sdr_state == 'absent'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/remove_sdr.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/remove_sdr.yml
new file mode 100644
index 000000000..3bf33b6ea
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/remove_sdr.yml
@@ -0,0 +1,120 @@
+---
+- name: Get configured MDM IP addresses
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ state: "present"
+ register: powerflex_sdr_mdm_ip_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Set fact - PowerFlex version
+ ansible.builtin.set_fact:
+ powerflex_sdr_array_version: "{{ powerflex_sdr_mdm_ip_result.mdm_cluster_details.master.versionInfo[1] }}"
+
+- name: Include the sdr_set_facts.yml
+ ansible.builtin.include_tasks: sdr_set_facts.yml
+
+- name: Login to mdm for PowerFlex version below 4.x
+ ansible.builtin.command: >
+ scli --login --mdm_ip {{ powerflex_sdr_mdm_primary_ip }}
+ --username admin
+ --password "{{ powerflex_mdm_password }}"
+ --approve_certificate
+ run_once: true
+ register: powerflex_initial_login
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_initial_login.rc == 0
+ no_log: true
+ when: powerflex_sdr_array_version == "3"
+
+- name: Login to mdm for PowerFlex version 4.x
+ ansible.builtin.command: >
+ scli --login --management_system_ip {{ hostname }}
+ --username admin
+ --password "{{ password }}"
+ --approve_certificate
+ run_once: true
+ register: powerflex_initial_login
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_initial_login.rc == 0
+ no_log: true
+ when: powerflex_sdr_array_version != "3"
+
+- name: Output msg of previous task login to mdm
+ ansible.builtin.debug:
+ var: powerflex_initial_login.stdout
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+
+- name: Checking if SDR already exists or not for PowerFlex version below 4.x
+ ansible.builtin.command: >
+ scli --mdm_ip {{ powerflex_sdr_mdm_primary_ip }}
+ --query_sdr
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ register: check_sdr_exists
+ failed_when: false
+ changed_when: check_sdr_exists.rc == 0
+ when: powerflex_sdr_array_version == "3"
+
+- name: Checking if SDR already exists or not for PowerFlex version 4.x
+ ansible.builtin.command: >
+ scli --management_system_ip {{ hostname }}
+ --query_sdr
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ register: check_sdr_exists
+ failed_when: false
+ changed_when: check_sdr_exists.rc == 0
+ when: powerflex_sdr_array_version != "3"
+
+- name: Skipping remove SDR if does not exist
+ ansible.builtin.debug:
+ msg: "SDR name {{ powerflex_sdr_hostname }} does not exist, will skip removing SDR."
+ when: check_sdr_exists.rc == 7
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+
+- name: Removing SDR for PowerFlex version below 4.x
+ ansible.builtin.command: >
+ scli --remove_sdr --mdm_ip {{ powerflex_sdr_mdm_primary_ip }}
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ register: powerflex_remove_sdr_output
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_remove_sdr_output.rc == 0
+ when: check_sdr_exists.rc == 0 and powerflex_sdr_array_version == "3"
+
+- name: Removing SDR for PowerFlex version 4.x
+ ansible.builtin.command: >
+ scli --remove_sdr --management_system_ip {{ hostname }}
+ --sdr_name "{{ powerflex_sdr_hostname }}"
+ register: powerflex_remove_sdr_output
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_remove_sdr_output.rc == 0
+ when: check_sdr_exists.rc == 0 and powerflex_sdr_array_version != "3"
+
+- name: Uninstall package
+ register: powerflex_sdr_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-sdr
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+- name: Uninstall deb package
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - emc-scaleio-sdr
+ when: ansible_distribution == "Ubuntu"
+
+- name: Logging out of the mdm
+ ansible.builtin.command: scli --logout
+ register: powerflex_mdm_logout
+ run_once: true
+ delegate_to: "{{ powerflex_sdr_mdm_primary_hostname }}"
+ changed_when: powerflex_mdm_logout.rc == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/sdr_set_facts.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/sdr_set_facts.yml
new file mode 100644
index 000000000..086b8b5bd
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/tasks/sdr_set_facts.yml
@@ -0,0 +1,7 @@
+---
+- name: Set facts for powerflex primary ip and hostname for mdm and sdr
+ ansible.builtin.set_fact:
+ powerflex_sdr_mdm_primary_ip: "{{ hostvars[groups['mdm'][0]]['ansible_host'] }}"
+ powerflex_sdr_mdm_primary_hostname: "{{ hostvars[groups['mdm'][0]]['inventory_hostname'] }}"
+ powerflex_sdr_ip: "{{ hostvars[inventory_hostname]['ansible_host'] }}"
+ powerflex_sdr_hostname: "{{ inventory_hostname }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/vars/main.yml
new file mode 100644
index 000000000..6a0f1ad81
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sdr/vars/main.yml
@@ -0,0 +1,2 @@
+---
+# vars file for powerflex_sdr
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/README.md
new file mode 100644
index 000000000..af7061108
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/README.md
@@ -0,0 +1,243 @@
+# powerflex_sds
+
+Role to manage the installation and uninstallation of Powerflex SDS.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td>IP or FQDN of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td>10.1.1.1</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td>The username of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td>admin</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td>The password of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td>password</td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>false</td>
+ <td>Port</td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>If C(false), the SSL certificates will not be validated.<br>Configure C(false) only on personally controlled sites where self-signed certificates are used.</td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>timeout</td>
+ <td>false</td>
+ <td>Timeout</td>
+ <td></td>
+ <td>int</td>
+ <td>120</td>
+ </tr>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>true</td>
+ <td>Location of installation and rpm gpg files to be installed.
+ <br>The required, compatible installation software package based on the operating system of the node.
+ <br>The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>str</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_protection_domain</td>
+ <td>true</td>
+ <td>The name of the protection domain to which the SDS will be added.
+ </td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_storage_pool</td>
+ <td>true</td>
+ <td>The name of the storage pool to which the device will be added.
+ </td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_disks</td>
+ <td>true</td>
+ <td>Disks for adding the device.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_role</td>
+ <td>true</td>
+ <td>Role of the SDS.</td>
+ <td>'sdsOnly', 'sdcOnly', 'all'</td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_device_media_type</td>
+ <td>true</td>
+ <td>Media type of the device.</td>
+ <td>'HDD', 'SSD', 'NVDIMM'</td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_device_name</td>
+ <td>true</td>
+ <td>Name of the device added to the SDS.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_external_acceleration_type</td>
+ <td>true</td>
+ <td>External acceleration type of the device added.</td>
+ <td>'Invalid', 'None', 'Read', 'Write', 'ReadAndWrite'</td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>powerflex_sds_fault_set</td>
+ <td>false</td>
+ <td>Fault set to which the SDS will be added.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+<tr>
+ <td>powerflex_sds_state</td>
+ <td>false</td>
+ <td>State of the SDS.</td>
+ <td>present, absent</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: "Install and configure powerflex SDS"
+ ansible.builtin.import_role:
+ name: "powerflex_sds"
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_sds_disks:
+ ansible_available_disks:
+ - '/dev/sdb'
+ powerflex_sds_disks_type: HDD
+ powerflex_sds_protection_domain: domain1
+ powerflex_sds_storage_pool: pool1
+ powerflex_sds_role: all
+ powerflex_sds_device_media_type: HDD
+ powerflex_sds_device_name: '/dev/sdb'
+ powerflex_sds_external_acceleration_type: ReadAndWrite
+ powerflex_sds_state: present
+
+ - name: "Uninstall powerflex SDS"
+ ansible.builtin.import_role:
+ name: "powerflex_sds"
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_sds_state: 'absent'
+
+```
+
+## Usage instructions
+----
+### To install all dependency packages, including SDS, on node:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+### To uninstall SDS:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies
+Trisha Datta (ansible.team@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/defaults/main.yml
new file mode 100644
index 000000000..033c766b5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/defaults/main.yml
@@ -0,0 +1,4 @@
+---
+file_glob_name: sds
+i_am_sure: 1
+powerflex_sds_state: present
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/argument_spec.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/argument_spec.yml
new file mode 100644
index 000000000..9b5e44cbe
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/argument_spec.yml
@@ -0,0 +1,88 @@
+---
+argument_specs:
+ main:
+ short_description: Role to manage the installation and uninstallation of Powerflex SDS.
+ description:
+ - Role to manage the installation and uninstallation of Powerflex SDS.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: IP or FQDN of the PowerFlex gateway.
+ username:
+ required: true
+ type: str
+ description: The username of the PowerFlex gateway.
+ password:
+ required: true
+ type: str
+ description: The password of the PowerFlex gateway.
+ port:
+ type: int
+ description: Port of the PowerFlex gateway.
+ default: 443
+ validate_certs:
+ description:
+ - If C(false), the SSL certificates will not be validated.
+ - Configure C(false) only on personally controlled sites where self-signed certificates are used.
+ type: bool
+ default: false
+ timeout:
+ description: Timeout.
+ type: int
+ default: 120
+ powerflex_common_file_install_location:
+ description:
+ - Location of installation and rpm gpg files to be installed.
+ - The required, compatible installation software package based on the operating system of the node.
+ - The files can be downloaded from the Dell Product support page for PowerFlex software.
+ type: str
+ default: /var/tmp
+ powerflex_sds_state:
+ description:
+ - Specifies the state of SDS.
+ type: str
+ choices: ['absent', 'present']
+ default: present
+ powerflex_sds_protection_domaine:
+ required: true
+ description:
+ - The name of the protection domain to which the SDS will be added.
+ type: str
+ powerflex_sds_storage_pool:
+ required: true
+ description:
+ - The name of the storage pool to which the device will be added.
+ type: str
+ powerflex_sds_disks:
+ required: true
+ description:
+ - Disks for adding the device.
+ type: str
+ powerflex_sds_role:
+ required: true
+ description:
+ - Role of the SDS
+ type: str
+ choices: ['sdsOnly', 'sdcOnly', 'all']
+ powerflex_sds_device_media_type:
+ required: true
+ description:
+ - Media type of the device.
+ type: str
+ choices: ['HDD', 'SSD', 'NVDIMM']
+ powerflex_sds_device_name:
+ required: true
+ description:
+ - Name of the SDS device.
+ type: str
+ powerflex_sds_external_acceleration_type:
+ required: true
+ description:
+ - External acceleration type of the device added.
+ type: str
+ choices: ['Invalid', 'None', 'Read', 'Write', 'ReadAndWrite']
+ powerflex_sds_fault_set:
+ description:
+ - Fault set to which the SDS will be added.
+ type: str
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/main.yml
new file mode 100644
index 000000000..999d95e6e
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/meta/main.yml
@@ -0,0 +1,24 @@
+---
+galaxy_info:
+ author: Trisha Datta
+ description: The role helps to manage the installation of SDS.
+ company: Dell Technologies
+ license: GPL-3.0-only
+ role_name: powerflex_sds
+ namespace: dellemc
+
+ min_ansible_version: "2.14.0"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/converge.yml
new file mode 100644
index 000000000..0dc711a2c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/converge.yml
@@ -0,0 +1,55 @@
+---
+- name: SDS installation
+ hosts: sds
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ tasks:
+ - name: Install common packages
+ ansible.builtin.import_role:
+ name: powerflex_common
+ vars:
+ powerflex_sds_state: present
+
+ - name: Install and configure powerflex SDS
+ ansible.builtin.import_role:
+ name: powerflex_sds
+ vars:
+ powerflex_sds_state: present
+
+ - name: Verifying device in normal mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_sds_add_device_output.device_details.mediaType == "{{ powerflex_sds_device_media_type }}"
+ - powerflex_sds_add_device_output.device_details.name == "{{ powerflex_sds_device_name }}"
+ - powerflex_sds_add_device_output.device_details.externalAccelerationType == "{{ powerflex_sds_external_acceleration_type }}"
+ - powerflex_sds_add_device_output.device_details.storagepoolPoolName == "{{ powerflex_sds_storage_pool }}"
+ - powerflex_sds_add_device_output.device_details.protectionDomainName == "{{ powerflex_sds_protection_domain }}"
+ when:
+ - not ansible_check_mode
+ - powerflex_sds_add_device_output.changed
+
+ - name: Verifying install package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_install_package_output.msg == "Check mode: No changes made"
+ when: ansible_check_mode
+
+ - name: Verifying installation package
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when:
+ - not ansible_check_mode
+ - powerflex_common_install_package_output.changed
+
+ - name: Verifying device in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_sds_add_device_output.device_details.mediaType == "{{ powerflex_sds_device_media_type }}"
+ - powerflex_sds_add_device_output.device_details.name == "{{ powerflex_sds_device_name }}"
+ - powerflex_sds_add_device_output.device_details.externalAccelerationType == "{{ powerflex_sds_external_acceleration_type }}"
+ - powerflex_sds_add_device_output.device_details.storagepoolPoolName == "{{ powerflex_sds_storage_pool }}"
+ - powerflex_sds_add_device_output.device_details.protectionDomainName == "{{ powerflex_sds_protection_domain }}"
+ when:
+ - not ansible_check_mode
+ - not powerflex_sds_add_device_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_installation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/converge.yml
new file mode 100644
index 000000000..fbb99419a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/converge.yml
@@ -0,0 +1,50 @@
+---
+- name: SDS uninstallation
+ hosts: sds
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ tasks:
+ - name: Uninstall powerflex SDS
+ register: powerflex_sds_uninstall_outputs
+ ansible.builtin.import_role:
+ name: powerflex_sds
+ vars:
+ powerflex_sds_state: absent
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_sds_uninstall_output.msg == "Check mode: No changes made"
+ - powerflex_sds_uninstall_output.changed
+ when: ansible_check_mode
+
+ - name: Verifying remove the sds in normal mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_sds_remove_result.sds_details is None
+ when:
+ - not ansible_check_mode
+ - powerflex_sds_remove_result.changed
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_sds_uninstall_output.results[0].msg == 'Nothing to do'
+ when:
+ - not ansible_check_mode
+ - not powerflex_sds_uninstall_output.changed
+
+ - name: Verifying remove the sds in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_sds_remove_result.msg == "Check mode: No changes made"
+ - powerflex_sds_remove_result.changed
+ when: ansible_check_mode
+
+ - name: Verifying remove the sds in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_sds_remove_result.sds_details is None
+ when:
+ - not ansible_check_mode
+ - not powerflex_sds_remove_result.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/sds_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/var_values.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/var_values.yml
new file mode 100644
index 000000000..b8d4ddc74
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/molecule/var_values.yml
@@ -0,0 +1,11 @@
+---
+powerflex_sds_disks:
+ansible_available_disks:
+ - '/dev/sdb'
+powerflex_sds_disks_type: HDD
+powerflex_sds_protection_domain: domain1
+powerflex_sds_storage_pool: pool1
+powerflex_sds_role: all
+powerflex_sds_device_media_type: HDD
+powerflex_sds_device_name: '/dev/sdb'
+powerflex_sds_external_acceleration_type: ReadAndWrite
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/install_sds.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/install_sds.yml
new file mode 100644
index 000000000..8887ff13c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/install_sds.yml
@@ -0,0 +1,112 @@
+---
+- name: Get configured MDM IP addresses
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ state: "present"
+ register: powerflex_sds_mdm_ip_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Set fact - PowerFlex version
+ ansible.builtin.set_fact:
+ powerflex_sds_array_version: "{{ powerflex_sds_mdm_ip_result.mdm_cluster_details.master.versionInfo[1] }}"
+
+- name: Set fact - powerflex_sds_mdm_ips
+ ansible.builtin.set_fact:
+ powerflex_sds_mdm_ips: "{{ powerflex_sds_mdm_ip_result.mdm_cluster_details.mdmAddresses | join(',') }}"
+ powerflex_sds_primary_mdm_hostname: "{{ hostvars[groups['mdm'][0]]['inventory_hostname'] }}"
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Collect only facts about hardware
+ ansible.builtin.setup:
+ gather_subset:
+ - hardware
+
+- name: Find disks
+ ansible.builtin.set_fact:
+ disks: hostvars[inventory_hostname].ansible_devices.keys() | list
+
+- name: Use local disk variable
+ when: powerflex_sds_disks
+ ansible.builtin.set_fact:
+ disks: "{{ powerflex_sds_disks }}"
+
+- name: Login to MDM for PowerFlex version 4.x
+ ansible.builtin.command: scli --login --management_system_ip {{ hostname }} --username {{ username }} --password {{ password }} --approve_certificate
+ run_once: true
+ register: powerflex_sds_login_output
+ changed_when: powerflex_sds_login_output.rc == 0
+ delegate_to: "{{ powerflex_sds_primary_mdm_hostname }}"
+ when: powerflex_sds_array_version != "3"
+
+- name: Login to MDM for PowerFlex version below 4.x
+ ansible.builtin.command: scli --login --username {{ username }} --password {{ password }} --approve_certificate
+ run_once: true
+ register: powerflex_sds_login_output
+ changed_when: powerflex_sds_login_output.rc == 0
+ delegate_to: "{{ powerflex_sds_primary_mdm_hostname }}"
+ when: powerflex_sds_array_version == "3"
+
+- name: Create SDS
+ dellemc.powerflex.sds:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ sds_name: "{{ inventory_hostname }}"
+ protection_domain_name: "{{ powerflex_sds_protection_domain }}"
+ sds_ip_list:
+ - ip: "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}"
+ role: "{{ powerflex_sds_role }}"
+ sds_ip_state: "present-in-sds"
+ state: "present"
+ register: powerflex_sds_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+ when: powerflex_sds_fault_set is not defined
+
+- name: Add SDS with fault set for PowerFlex version 4.x
+ ansible.builtin.command:
+ scli --add_sds --management_system_ip {{ hostname }}
+ --sds_ip {{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}
+ --storage_pool_name {{ powerflex_sds_storage_pool }} --sds_name "{{ inventory_hostname }}"
+ --protection_domain_name {{ powerflex_sds_protection_domain }} --fault_set_name {{ powerflex_sds_fault_set }}
+ register: add_sds
+ changed_when: ('already in use' in add_sds.stderr) or (add_sds.rc == 0)
+ delegate_to: "{{ powerflex_sds_primary_mdm_hostname }}"
+ ignore_errors: true
+ when: powerflex_sds_fault_set is defined and powerflex_sds_array_version != "3"
+
+- name: Add SDS with fault set for PowerFlex version below 4.x
+ ansible.builtin.command:
+ scli --add_sds --mdm_ip {{ powerflex_sds_mdm_ips }}
+ --sds_ip {{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}
+ --storage_pool_name {{ powerflex_sds_storage_pool }} --sds_name "{{ inventory_hostname }}"
+ --protection_domain_name {{ powerflex_sds_protection_domain }} --fault_set_name {{ powerflex_sds_fault_set }}
+ register: add_sds
+ changed_when: ('already in use' in add_sds.stderr) or (add_sds.rc == 0)
+ delegate_to: "{{ powerflex_sds_primary_mdm_hostname }}"
+ ignore_errors: true
+ when: powerflex_sds_fault_set is defined and powerflex_sds_array_version == "3"
+
+- name: Add a device
+ dellemc.powerflex.device:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ current_pathname: "{{ disks.ansible_available_disks | join(',') }}"
+ sds_name: "{{ inventory_hostname }}"
+ media_type: "{{ powerflex_sds_device_media_type }}"
+ device_name: "{{ powerflex_sds_device_name }}"
+ storage_pool_name: "{{ powerflex_sds_storage_pool }}"
+ protection_domain_name: "{{ powerflex_sds_protection_domain }}"
+ external_acceleration_type: "{{ powerflex_sds_external_acceleration_type }}"
+ force: true
+ state: "present"
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+ when: disks.ansible_available_disks | length > 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/main.yml
new file mode 100644
index 000000000..04fe23630
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Install SDS
+ ansible.builtin.include_tasks: install_sds.yml
+ when: powerflex_sds_state == 'present'
+
+- name: Remove SDS
+ ansible.builtin.include_tasks: uninstall_sds.yml
+ when: powerflex_sds_state == 'absent'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/uninstall_sds.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/uninstall_sds.yml
new file mode 100644
index 000000000..af5609e57
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/tasks/uninstall_sds.yml
@@ -0,0 +1,31 @@
+---
+- name: Remove SDS
+ dellemc.powerflex.sds:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ sds_name: "{{ inventory_hostname }}"
+ state: "absent"
+ register: powerflex_sds_remove_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Uninstall package
+ register: powerflex_sds_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-sds
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+- name: Uninstall deb package
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - emc-scaleio-sds
+ when: ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_sds/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/vars/main.yml
new file mode 100644
index 000000000..af154c9d9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_sds/vars/main.yml
@@ -0,0 +1,5 @@
+---
+file_glob_name: sds
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_sds_mdm_ips }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/README.md
new file mode 100644
index 000000000..dec61fec9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/README.md
@@ -0,0 +1,210 @@
+# powerflex_tb
+
+Role to manage the installation and uninstallation of Powerflex TB.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Notes](#notes)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td>IP or FQDN of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td>The username of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td>The password of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>false</td>
+ <td>Port of the PowerFlex gateway.</td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>If C(false), the SSL certificates will not be validated.<br>Configure C(false) only on personally controlled sites where self-signed certificates are used.</td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>timeout</td>
+ <td>false</td>
+ <td>Timeout.</td>
+ <td></td>
+ <td>int</td>
+ <td>120</td>
+ </tr>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>false</td>
+ <td>Location of installation and rpm gpg files to be installed.
+ <br>The required, compatible installation software package based on the operating system of the node.
+ <br> The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>str</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_tb_state</td>
+ <td>false</td>
+ <td>Specify state of TB.<br></td>
+ <td>absent, present</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+ <tr>
+ <td>powerflex_tb_primary_name</td>
+ <td>false</td>
+ <td>Name of the primary TB.<br></td>
+ <td></td>
+ <td>str</td>
+ <td>primary_tb</td>
+ </tr>
+ <tr>
+ <td>powerflex_tb_secondary_name</td>
+ <td>false</td>
+ <td>Name of the secondary TB.<br></td>
+ <td></td>
+ <td>str</td>
+ <td>secondary_tb</td>
+ </tr>
+ <tr>
+ <td>powerflex_tb_cluster_mode</td>
+ <td>false</td>
+ <td>Mode of the cluster.<br></td>
+ <td>ThreeNodes, FiveNodes</td>
+ <td>str</td>
+ <td>ThreeNodes</td>
+ </tr>
+ <tr>
+ <td>powerflex_tb_cert_password</td>
+ <td>false</td>
+ <td>The CLI certificate password for login to the primary MDM.<br></td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Install and configure PowerFlex TB
+ ansible.builtin.import_role:
+ name: "powerflex_tb"
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_tb_primary_name: "primary_tb"
+ powerflex_tb_secondary_name: "secondary_tb"
+ powerflex_tb_cluster_mode: "ThreeNodes"
+ powerflex_common_file_install_location: "/var/tmp"
+ powerflex_tb_state: present
+
+ - name: Uninstall powerflex TB
+ ansible.builtin.import_role:
+ name: "powerflex_tb"
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_tb_state: 'absent'
+
+```
+
+## Notes
+----
+
+- As a pre-requisite for PowerFlex 3.6, the Gateway must be installed.
+- For PowerFlex 4.x, after installing the TB perform initial configuration steps on PowerFlex Manager GUI. These steps can be found in Install and Update of Dell PowerFlex 4.x from Dell Support page.
+
+## Usage instructions
+----
+### To install all dependency packages, including TB, on node:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory site_powerflex45.yml
+ ```
+
+### To uninstall TB:
+- PowerFlex 3.6:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+- PowerFlex 4.5:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex45.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Ananthu S Kuttattu (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/defaults/main.yml
new file mode 100644
index 000000000..b4b0b5a30
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/defaults/main.yml
@@ -0,0 +1,8 @@
+---
+# defaults file for powerflex_tb
+powerflex_tb_primary_name: primary_tb
+powerflex_tb_secondary_name: secondary_tb
+powerflex_tb_cluster_mode: "ThreeNodes"
+file_glob_name: mdm
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_tb_mdm_ips }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_spec.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_spec.yml
new file mode 100644
index 000000000..f3072df80
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_spec.yml
@@ -0,0 +1,85 @@
+---
+argument_specs:
+ main:
+ short_description: Role to manage the installation and uninstallation of Powerflex TB.
+ description:
+ - Role to manage the installation and uninstallation of Powerflex TB.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: IP or FQDN of the PowerFlex gateway.
+ username:
+ required: true
+ type: str
+ description: The username of the PowerFlex gateway.
+ password:
+ required: true
+ type: str
+ description: The password of the PowerFlex gateway.
+ port:
+ type: int
+ description: Port of the PowerFlex gateway.
+ default: 443
+ validate_certs:
+ description:
+ - If C(false), the SSL certificates will not be validated.
+ - Configure C(false) only on personally controlled sites where self-signed certificates are used.
+ type: bool
+ default: false
+ timeout:
+ description: Timeout.
+ type: int
+ default: 120
+ powerflex_common_file_install_location:
+ description:
+ - Location of installation and rpm gpg files to be installed.
+ - The required, compatible installation software package based on the operating system of the node.
+ type: str
+ default: /var/tmp
+ powerflex_tb_state:
+ description:
+ - Specify state of TB.
+ type: str
+ choices: ['absent', 'present']
+ default: present
+ powerflex_tb_primary_name:
+ required: true
+ description:
+ - Name of the primary TB.
+ type: str
+ default: 'primary_tb'
+ powerflex_tb_secondary_name:
+ required: true
+ description:
+ - Name of the secondary TB.
+ type: str
+ default: 'secondary_tb'
+ powerflex_tb_cluster_mode:
+ required: true
+ description:
+ - Mode of the cluster.
+ choices: ['ThreeNodes', 'FiveNodes']
+ type: str
+ default: 'ThreeNodes'
+ powerflex_protection_domain_name:
+ description:
+ - Name of the protection domain.
+ type: str
+ default: 'tb_protection_domain'
+ powerflex_fault_sets:
+ description:
+ - List of fault sets.
+ type: list
+ default: ['fs1', 'fs2', 'fs3']
+ powerflex_media_type:
+ description:
+ - Media type of the storage pool.
+ type: str
+ choices: ['SSD', 'HDD', 'TRANSITIONAL']
+ default: 'SSD'
+ powerflex_storage_pool_name:
+ description:
+ - Name of the storage pool.
+ type: str
+ default: 'tb_storage_pool'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_specs.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_specs.yml
new file mode 100644
index 000000000..ac5a3e3ef
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/argument_specs.yml
@@ -0,0 +1,65 @@
+---
+argument_specs:
+ main:
+ short_description: Role to manage the installation and uninstallation of Powerflex TB.
+ description:
+ - Role to manage the installation and uninstallation of Powerflex TB.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: IP or FQDN of the PowerFlex gateway.
+ username:
+ required: true
+ type: str
+ description: The username of the PowerFlex gateway.
+ password:
+ required: true
+ type: str
+ description: The password of the PowerFlex gateway.
+ port:
+ type: int
+ description: Port of the PowerFlex gateway.
+ default: 443
+ validate_certs:
+ description:
+ - If C(false), the SSL certificates will not be validated.
+ - Configure C(false) only on personally controlled sites where self-signed certificates are used.
+ type: bool
+ default: false
+ timeout:
+ description: Timeout.
+ type: int
+ default: 120
+ powerflex_common_file_install_location:
+ description:
+ - Location of installation and rpm gpg files to be installed.
+ - The required, compatible installation software package based on the operating system of the node.
+ type: str
+ default: /var/tmp
+ powerflex_tb_state:
+ description:
+ - Specify state of TB.
+ type: str
+ choices: ['absent', 'present']
+ default: present
+ powerflex_tb_primary_name:
+ description:
+ - Name of the primary TB.
+ type: str
+ default: 'primary_tb'
+ powerflex_tb_secondary_name:
+ description:
+ - Name of the secondary TB.
+ type: str
+ default: 'secondary_tb'
+ powerflex_tb_cluster_mode:
+ description:
+ - Mode of the cluster.
+ choices: ['ThreeNodes', 'FiveNodes']
+ type: str
+ default: 'ThreeNodes'
+ powerflex_tb_cert_password:
+ description:
+ - The CLI certificate password for login to the primary MDM.
+ type: str
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/main.yml
new file mode 100644
index 000000000..c3179cd1e
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/meta/main.yml
@@ -0,0 +1,25 @@
+---
+galaxy_info:
+ author: Ananthu S Kuttattu
+ description: Role to manage the installation and uninstallation of Powerflex TB.
+ company: Dell Technologies
+ license: GPL-3.0-only
+ role_name: powerflex_tb
+ namespace: dellemc
+
+ min_ansible_version: "2.14.0"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/converge.yml
new file mode 100644
index 000000000..77d00ec11
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/converge.yml
@@ -0,0 +1,35 @@
+---
+- name: TB installation
+ hosts: tb
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: Install common packages
+ ansible.builtin.import_role:
+ name: powerflex_common
+
+ - name: "Install PowerFlex TieBreaker"
+ ansible.builtin.import_role:
+ name: "powerflex_tb"
+ vars:
+ powerflex_tb_state: present
+ register: powerflex_tb_results
+
+ - name: "Verifying installation package"
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: "Verifying cluster mode switch from 1 node to 3 node MDM cluster"
+ ansible.builtin.assert:
+ that:
+ - powerflex_tb_cluster_to_three_output.stdout == "Successfully switched the cluster mode."
+ when: not ansible_check_mode and powerflex_tb_cluster_to_three_output.changed and powerflex_tb_cluster_mode == "ThreeNodes"
+
+ - name: "Verifying cluster mode switch from 1 node to 5 node MDM cluster"
+ ansible.builtin.assert:
+ that:
+ - powerflex_tb_cluster_to_five_output.stdout == "Successfully switched the cluster mode."
+ when: not ansible_check_mode and powerflex_tb_cluster_to_five_output.changed and powerflex_tb_cluster_mode == "FiveNodes"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_installation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/converge.yml
new file mode 100644
index 000000000..986b270de
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/converge.yml
@@ -0,0 +1,19 @@
+---
+- name: TB uninstallation
+ hosts: tb
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: "Uninstall powerflex TB"
+ register: powerflex_tb_uninstall_outputs
+ ansible.builtin.import_role:
+ name: "powerflex_tb"
+ vars:
+ powerflex_tb_state: 'absent'
+
+ - name: "Verifying remove the TB"
+ ansible.builtin.assert:
+ that:
+ - powerflex_tb_remove_primary_tb_output.stdout == "Successfully removed the standby MDM."
+ when: not ansible_check_mode and powerflex_tb_remove_primary_tb_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/tb_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/var_values.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/var_values.yml
new file mode 100644
index 000000000..01397a639
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/var_values.yml
@@ -0,0 +1,7 @@
+---
+powerflex_tb_primary_name: primary_tb
+powerflex_tb_secondary_name: secondary_tb
+powerflex_tb_cluster_mode: "ThreeNodes"
+powerflex_protection_domain_name: "tb_protection_domain"
+powerflex_fault_sets: ['fs1', 'fs2', 'fs3']
+powerflex_storage_pool_name: "tb_storage_pool"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/converge.yml
new file mode 100644
index 000000000..c9322f319
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/converge.yml
@@ -0,0 +1,20 @@
+---
+- name: Providing incorrect credentials for TB node
+ hosts: tb
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: false
+ tasks:
+ - name: "Install and configure powerflex tb with wrong credentials"
+ ansible.builtin.import_role:
+ name: "powerflex_tb"
+ vars:
+ powerflex_tb_state: present
+ ignore_unreachable: true
+ ignore_errors: true
+ register: powerflex_tb_wrong_credentials_output
+
+ - name: "Verifying failure of install package with wrong credentials"
+ ansible.builtin.assert:
+ that:
+ - " 'Communication error' in powerflex_tb_primary_output.msg"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/inventory b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/inventory
new file mode 100644
index 000000000..391105e2b
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/inventory
@@ -0,0 +1,4 @@
+node0 ansible_host=10.2.2.2 ansible_port=22 ansible_ssh_pass=wrongpassword ansible_user=root
+
+[tb]
+node0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/molecule.yml
new file mode 100644
index 000000000..805f92879
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/molecule/wrong_tb_credentials/molecule.yml
@@ -0,0 +1,11 @@
+---
+provisioner:
+ name: ansible
+ inventory:
+ links:
+ hosts: inventory
+ group_vars: ../../../../playbooks/roles/group_vars/
+ host_vars: ../../../../playbooks/roles/host_vars/
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb.yml
new file mode 100644
index 000000000..504b3e920
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb.yml
@@ -0,0 +1,8 @@
+---
+- name: Install TB for PowerFlex below 4.x
+ ansible.builtin.include_tasks: install_tb3x.yml
+ when: powerflex_tb_scli_version[0] == '3'
+
+- name: Install TB for PowerFlex 4.x
+ ansible.builtin.include_tasks: install_tb4x.yml
+ when: powerflex_tb_scli_version[0] >= '4'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb3x.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb3x.yml
new file mode 100644
index 000000000..e602351da
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb3x.yml
@@ -0,0 +1,81 @@
+---
+- name: Get configured MDM IP addresses
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ state: "present"
+ register: powerflex_tb_mdm_ip_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Set fact - powerflex_mdm_ips
+ ansible.builtin.set_fact:
+ powerflex_tb_mdm_ips: "{{ powerflex_tb_mdm_ip_result.mdm_cluster_details.mdmAddresses | join(',') }}"
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Login with password
+ ansible.builtin.command: scli --login --username {{ username }} --password "{{ password }}"
+ run_once: true
+ register: powerflex_tb_login_output
+ changed_when: powerflex_tb_login_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+
+- name: Add primary TB
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ mdm_name: "{{ powerflex_tb_primary_name }}"
+ standby_mdm:
+ mdm_ips:
+ - "{{ powerflex_tb_primary_ip }}"
+ role: "TieBreaker"
+ management_ips:
+ - "{{ powerflex_tb_primary_ip }}"
+ state: "present"
+ register: powerflex_tb_primary_output
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Add secondary TB
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ mdm_name: "{{ powerflex_tb_secondary_name }}"
+ standby_mdm:
+ mdm_ips:
+ - "{{ powerflex_tb_secondary_ip }}"
+ role: "TieBreaker"
+ management_ips:
+ - "{{ powerflex_tb_secondary_ip }}"
+ state: "present"
+ register: powerflex_tb_secondary_output
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+ when: powerflex_tb_secondary_ip is defined
+
+- name: Switch to cluster three node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "3_node" --add_slave_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}" --add_tb_ip "{{ powerflex_tb_primary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_to_three_output
+ changed_when: powerflex_tb_cluster_to_three_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_primary_output.mdm_cluster_details.clusterMode != "ThreeNodes" and powerflex_tb_cluster_mode == "ThreeNodes"
+
+- name: Switch to cluster five node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "5_node" --add_slave_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}","{{ powerflex_tb_mdm_tertiary_ip }}" --add_tb_ip "{{ powerflex_tb_primary_ip }}","{{ powerflex_tb_secondary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_to_five_output
+ changed_when: powerflex_tb_cluster_to_five_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_primary_output.mdm_cluster_details.clusterMode != "FiveNodes" and powerflex_tb_cluster_mode == "FiveNodes"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb4x.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb4x.yml
new file mode 100644
index 000000000..d34857ba4
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/install_tb4x.yml
@@ -0,0 +1,69 @@
+---
+- name: Set fact - powerflex_mdm_ips
+ ansible.builtin.set_fact:
+ powerflex_tb_mdm_ips: "{{ powerflex_tb_mdm_primary_ip }},{{ powerflex_tb_mdm_secondary_ip }}"
+ when: powerflex_tb_mdm_count | int == 2
+
+- name: Set fact - powerflex_mdm_ips
+ ansible.builtin.set_fact:
+ powerflex_tb_mdm_ips: "{{ powerflex_tb_mdm_primary_ip }},{{ powerflex_tb_mdm_secondary_ip }},{{ powerflex_tb_mdm_tertiary_ip }}"
+ when: powerflex_tb_mdm_count | int > 2
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
+
+- name: Login to primary MDM node
+ ansible.builtin.command: >
+ scli --login --p12_path /opt/emc/scaleio/mdm/cfg/cli_certificate.p12 --p12_password {{ powerflex_tb_cert_password }}
+ run_once: true
+ register: powerflex_tb_login_output
+ changed_when: powerflex_tb_login_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+
+- name: Add primary TB
+ ansible.builtin.command: >
+ scli --add_standby_mdm
+ --new_mdm_ip {{ powerflex_tb_primary_ip }}
+ --mdm_role tb
+ --new_mdm_name {{ powerflex_tb_primary_name }}
+ --new_mdm_management_ip {{ powerflex_tb_primary_ip }}
+ run_once: true
+ register: powerflex_tb_primary_output
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_primary_ip is defined
+ ignore_errors: true
+ changed_when: powerflex_tb_primary_output.rc == 0
+
+- name: Add secondary TB
+ ansible.builtin.command: >
+ scli --add_standby_mdm
+ --new_mdm_ip {{ powerflex_tb_secondary_ip }}
+ --mdm_role tb
+ --new_mdm_name {{ powerflex_tb_secondary_name }}
+ --new_mdm_management_ip {{ powerflex_tb_secondary_ip }}
+ register: powerflex_tb_secondary_output
+ run_once: true
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_secondary_ip is defined
+ ignore_errors: true
+ changed_when: powerflex_tb_secondary_output.rc == 0
+
+- name: Switch to cluster three node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "3_node" --add_secondary_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}" --add_tb_ip "{{ powerflex_tb_primary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_to_three_output
+ changed_when: powerflex_tb_cluster_to_three_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_mdm_cluster_mode[0] != "3_node" and powerflex_tb_cluster_mode == "ThreeNodes"
+
+- name: Switch to cluster five node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "5_node" --add_secondary_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}","{{ powerflex_tb_mdm_tertiary_ip }}" --add_tb_ip "{{ powerflex_tb_primary_ip }}","{{ powerflex_tb_secondary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_to_five_output
+ changed_when: powerflex_tb_cluster_to_five_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_mdm_cluster_mode[0] != "5_node" and powerflex_tb_cluster_mode == "FiveNodes"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/main.yml
new file mode 100644
index 000000000..f98c09ff1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/main.yml
@@ -0,0 +1,31 @@
+---
+- name: Include set_tb_ips.yml
+ ansible.builtin.include_tasks: set_tb_ips.yml
+
+- name: Get SCli version
+ ansible.builtin.command: >
+ scli --query_cluster
+ register: powerflex_tb_scli_cluster_details
+ tags: register
+ changed_when: powerflex_tb_scli_cluster_details.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+
+- name: Extract the scli version
+ ansible.builtin.set_fact:
+ powerflex_tb_scli_version: "{{ input_query | ansible.builtin.regex_search('Version: (\\d+)\\.(\\d+)', '\\1\\2') }}"
+ vars:
+ input_query: "{{ powerflex_tb_scli_cluster_details.stdout }}"
+
+- name: Extract the cluster mode
+ ansible.builtin.set_fact:
+ powerflex_tb_mdm_cluster_mode: "{{ input_query | ansible.builtin.regex_search('Mode: (\\w+)', '\\1') }}"
+ vars:
+ input_query: "{{ powerflex_tb_scli_cluster_details.stdout }}"
+
+- name: Install TB
+ ansible.builtin.include_tasks: install_tb.yml
+ when: powerflex_tb_state == 'present'
+
+- name: Uninstall TB
+ ansible.builtin.include_tasks: uninstall_tb.yml
+ when: powerflex_tb_state == 'absent'
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/set_tb_ips.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/set_tb_ips.yml
new file mode 100644
index 000000000..34c0144d5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/set_tb_ips.yml
@@ -0,0 +1,29 @@
+---
+- name: Set TB count
+ ansible.builtin.set_fact:
+ powerflex_tb_count: "{{ groups['tb'] | length }}"
+ powerflex_tb_mdm_count: "{{ groups['mdm'] | length }}"
+
+- name: Set fact - powerflex_tb_mdm_primary_ip and powerflex_tb_mdm_secondary_ip
+ ansible.builtin.set_fact:
+ powerflex_tb_mdm_primary_ip: "{{ hostvars[groups['mdm'][0]]['ansible_host'] }}"
+ powerflex_tb_mdm_primary_hostname: "{{ hostvars[groups['mdm'][0]]['inventory_hostname'] }}"
+ powerflex_tb_mdm_secondary_ip: "{{ hostvars[groups['mdm'][1]]['ansible_host'] }}"
+ powerflex_tb_mdm_secondary_hostname: "{{ hostvars[groups['mdm'][1]]['inventory_hostname'] }}"
+
+- name: Set fact - powerflex_tb_mdm_tertiary_ip
+ ansible.builtin.set_fact:
+ powerflex_tb_mdm_tertiary_ip: "{{ hostvars[groups['tb'][2]]['ansible_host'] }}"
+ powerflex_tb_mdm_tertiary_hostname: "{{ hostvars[groups['tb'][2]]['inventory_hostname'] }}"
+ when: "powerflex_tb_mdm_count | int > 2"
+
+- name: Set fact - powerflex_tb_primary
+ ansible.builtin.set_fact:
+ powerflex_tb_primary_ip: "{{ hostvars[groups['tb'][0]]['ansible_host'] }}"
+ powerflex_tb_primary_hostname: "{{ hostvars[groups['tb'][0]]['inventory_hostname'] }}"
+
+- name: Set fact - powerflex_tb_primary
+ ansible.builtin.set_fact:
+ powerflex_tb_secondary_ip: "{{ hostvars[groups['tb'][1]]['ansible_host'] }}"
+ powerflex_tb_secondary_hostname: "{{ hostvars[groups['tb'][1]]['inventory_hostname'] }}"
+ when: "powerflex_tb_count | int > 1"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/uninstall_tb.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/uninstall_tb.yml
new file mode 100644
index 000000000..b08bffed8
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/tasks/uninstall_tb.yml
@@ -0,0 +1,97 @@
+---
+# Switch from three or five to cluster one node for PowerFlex version 3.6
+- name: Login to primary MDM node of PowerFlex version 3.x
+ ansible.builtin.command: scli --login --username {{ username }} --password "{{ password }}"
+ run_once: true
+ register: powerflex_tb_login_output
+ changed_when: powerflex_tb_login_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_scli_version[0] == '3'
+
+- name: Switch cluster mode from three nodes to one node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "1_node" --remove_slave_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}" --remove_tb_ip "{{ powerflex_tb_primary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_to_one_output
+ changed_when: powerflex_tb_cluster_to_one_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_mdm_cluster_mode[0] == "3_node" and powerflex_tb_scli_version[0] == '3'
+
+- name: Switch cluster mode from five nodes to one node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "1_node" --remove_slave_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}","{{ powerflex_tb_mdm_tertiary_ip }}" --remove_tb_ip "{{ powerflex_tb_primary_ip }}","{{ powerflex_tb_secondary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_to_one_output
+ changed_when: powerflex_tb_cluster_to_one_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_mdm_cluster_mode[0] == "5_node" and powerflex_tb_scli_version[0] == '3'
+
+# Switch from three or five to cluster one node for PowerFlex version 4.5
+- name: Login to primary MDM node of PowerFlex version 4.5
+ ansible.builtin.command: >
+ scli --login --management_system_ip {{ hostname }} --username {{ username }} --password {{ password }}
+ run_once: true
+ register: powerflex_tb_login_output
+ changed_when: powerflex_tb_login_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_scli_version[0] >= '4'
+
+- name: Switch cluster mode from three nodes to one node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "1_node" --remove_secondary_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}" --remove_tb_ip "{{ powerflex_tb_primary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_three_to_one_output
+ changed_when: powerflex_tb_cluster_three_to_one_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_mdm_cluster_mode[0] == "3_node" and powerflex_tb_scli_version[0] >= '4'
+
+- name: Switch cluster mode from five nodes to one node
+ ansible.builtin.command: |
+ scli --switch_cluster_mode --cluster_mode "1_node" --remove_secondary_mdm_ip
+ "{{ powerflex_tb_mdm_secondary_ip }}","{{ powerflex_tb_mdm_tertiary_ip }}" --remove_tb_ip "{{ powerflex_tb_primary_ip }}","{{ powerflex_tb_secondary_ip }}"
+ run_once: true
+ register: powerflex_tb_cluster_five_to_one_output
+ changed_when: powerflex_tb_cluster_five_to_one_output.rc == 0
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_mdm_cluster_mode[0] == "5_node" and powerflex_tb_scli_version[0] >= '4'
+
+# Remove the standby MDMs
+- name: Remove primary tb from standby mdm
+ ansible.builtin.command: scli --remove_standby_mdm --remove_mdm_ip "{{ powerflex_tb_primary_ip }}"
+ run_once: true
+ register: powerflex_tb_remove_primary_tb_output
+ changed_when: powerflex_tb_remove_primary_tb_output.rc == 0
+ ignore_errors: true
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+
+- name: Remove secondary tb from standby mdm
+ ansible.builtin.command: scli --remove_standby_mdm --remove_mdm_ip "{{ powerflex_tb_secondary_ip }}"
+ run_once: true
+ register: powerflex_tb_remove_secondary_tb_output
+ changed_when: powerflex_tb_remove_secondary_tb_output.rc == 0
+ ignore_errors: true
+ delegate_to: "{{ powerflex_tb_mdm_primary_hostname }}"
+ when: powerflex_tb_secondary_ip is defined
+
+- name: Uninstall package
+ register: powerflex_tb_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-mdm
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+- name: Uninstall deb package
+ register: powerflex_tb_uninstall_output
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - EMC-ScaleIO-mdm
+ when: ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_tb/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/vars/main.yml
new file mode 100644
index 000000000..aa01f740c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_tb/vars/main.yml
@@ -0,0 +1,6 @@
+---
+# vars file for powerflex_tb
+file_glob_name: mdm
+file_gpg_name: RPM-GPG-KEY-ScaleIO
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_tb_mdm_ips }}"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/README.md b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/README.md
new file mode 100644
index 000000000..794eb6b08
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/README.md
@@ -0,0 +1,165 @@
+# powerflex_webui
+
+Role to manage the installation and uninstallation of Powerflex Web UI.
+
+## Table of contents
+
+* [Requirements](#requirements)
+* [Ansible collections](#ansible-collections)
+* [Role Variables](#role-variables)
+* [Examples](#examples)
+* [Notes](#notes)
+* [Usage instructions](#usage-instructions)
+* [Author Information](#author-information)
+
+## Requirements
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.powerflex
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Description</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Default Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td>IP or FQDN of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td>The username of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td>The password of the PowerFlex gateway.</td>
+ <td></td>
+ <td>str</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>port</td>
+ <td>false</td>
+ <td>The port of the PowerFlex gateway.</td>
+ <td></td>
+ <td>int</td>
+ <td>443</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>If C(false), the SSL certificates will not be validated.<br>Configure C(false) only on personally controlled sites where self-signed certificates are used.</td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>timeout</td>
+ <td>false</td>
+ <td>Time after which connection will get terminated.</td>
+ <td></td>
+ <td>int</td>
+ <td>120</td>
+ </tr>
+ <tr>
+ <td>powerflex_common_file_install_location</td>
+ <td>false</td>
+ <td>Location of installation, compatible installation software package based on the operating system of the node.
+ <br> The files can be downloaded from the Dell Product support page for PowerFlex software.</td>
+ <td></td>
+ <td>path</td>
+ <td>/var/tmp</td>
+ </tr>
+ <tr>
+ <td>powerflex_webui_skip_java</td>
+ <td>false</td>
+ <td>Specifies whether to install java or not.<br></td>
+ <td></td>
+ <td>bool</td>
+ <td>false</td>
+ </tr>
+ <tr>
+ <td>powerflex_webui_state</td>
+ <td>false</td>
+ <td>Specify state of web UI.
+ <br>present will install the web UI and absent will uninstall the web UI.</td>
+ <td>absent, present</td>
+ <td>str</td>
+ <td>present</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+----
+```
+ - name: Install and configure powerflex web UI
+ ansible.builtin.import_role:
+ name: "powerflex_webui"
+ vars:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ port: "{{ port }}"
+ powerflex_common_file_install_location: "/opt/scaleio/rpm"
+ powerflex_webui_skip_java: true
+ powerflex_webui_state: present
+
+ - name: Uninstall powerflex web UI
+ ansible.builtin.import_role:
+ name: "powerflex_webui"
+ vars:
+ powerflex_webui_state: absent
+
+```
+## Notes
+- Supported only in PowerFlex version 3.6.
+
+## Usage instructions
+----
+### To install all dependency packages, including web UI, on node:
+ ```
+ ansible-playbook -i inventory site.yml
+ ```
+
+### To uninstall web UI:
+ ```
+ ansible-playbook -i inventory uninstall_powerflex.yml
+ ```
+
+Sample playbooks and inventory can be found in the playbooks directory.
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Trisha Datta (ansible.team@Dell.com) 2023
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/defaults/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/defaults/main.yml
new file mode 100644
index 000000000..fd2b592a8
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/defaults/main.yml
@@ -0,0 +1,6 @@
+---
+powerflex_skip_java: false
+file_glob_name: mgmt-server
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_webui_mdm_ips }}"
+powerflex_webui_state: "present"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/argument_specs.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/argument_specs.yml
new file mode 100644
index 000000000..50aee5bbe
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/argument_specs.yml
@@ -0,0 +1,52 @@
+---
+argument_specs:
+ main:
+ short_description: Role to manage the installation and uninstallation of Powerflex web UI.
+ description:
+ - Role to manage the installation and uninstallation of Powerflex web UI.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: IP or FQDN of the PowerFlex gateway.
+ username:
+ required: true
+ type: str
+ description: The username of the PowerFlex gateway.
+ password:
+ required: true
+ type: str
+ description: The password of the PowerFlex gateway.
+ port:
+ type: int
+ description: Port of the PowerFlex gateway.
+ default: 443
+ validate_certs:
+ description:
+ - If C(false), the SSL certificates will not be validated.
+ - Configure C(false) only on personally controlled sites where self-signed certificates are used.
+ type: bool
+ default: false
+ timeout:
+ description: Time after which connection will get terminated.
+ type: int
+ default: 120
+ powerflex_common_file_install_location:
+ description:
+ - Location of installation, compatible installation software package
+ based on the operating system of the node.
+ - The files can be downloaded from the Dell Product support page for PowerFlex software.
+ type: path
+ default: /var/tmp
+ powerflex_webui_skip_java:
+ type: bool
+ description: Specifies whether to install java or not.
+ default: false
+ powerflex_webui_state:
+ description:
+ - Specifies the state of the web UI.
+ - present will install the web UI if not already installed.
+ - absent will uninstall the web UI if installed.
+ type: str
+ choices: ['absent', 'present']
+ default: present
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/main.yml
new file mode 100644
index 000000000..2872690ea
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/meta/main.yml
@@ -0,0 +1,29 @@
+---
+galaxy_info:
+ role_name: powerflex_webui
+ author: Trisha Datta
+ namespace: dellemc
+ description: Role to manage the installation and uninstallation of Powerflex WebUI.
+ company: Dell Technologies
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.14.0"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+dependencies:
+ - role: powerflex_common
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/converge.yml
new file mode 100644
index 000000000..cd2b9c8b5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/converge.yml
@@ -0,0 +1,30 @@
+---
+- name: Converge
+ hosts: webui
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: Install and configure powerflex webui
+ ansible.builtin.import_role:
+ name: "powerflex_webui"
+ vars:
+ powerflex_webui_state: present
+
+ - name: Verifying installation package in check mode
+ ansible.builtin.assert:
+ that:
+ - " 'No changes made, but would have if not in check mode' in powerflex_common_install_package_output.msg"
+ when: ansible_check_mode
+
+ - name: Verifying installation package in converge
+ ansible.builtin.assert:
+ that:
+ - " 'Installed' in powerflex_common_install_package_output.results[0]"
+ when: not ansible_check_mode and powerflex_common_install_package_output.changed
+
+ - name: Verifying installation package in idempotency
+ ansible.builtin.assert:
+ that:
+ - " 'Nothing to do' in powerflex_common_install_package_output.msg"
+ when: not ansible_check_mode and not powerflex_common_install_package_output.changed
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/converge.yml
new file mode 100644
index 000000000..f614a1862
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/converge.yml
@@ -0,0 +1,34 @@
+---
+- name: Converge
+ hosts: webui
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: Install and configure powerflex webui with no rpm
+ ansible.builtin.import_role:
+ name: "powerflex_webui"
+ vars:
+ powerflex_common_file_install_location: "/opt/empty"
+ powerflex_webui_state: present
+ ignore_errors: true
+ register: powerflex_webui_install_config_no_rpm_result
+
+ - name: Verifying failure of install package with respect to no rpm file
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length == 0
+
+ - name: Install and configure powerflex webui with wrong file path
+ ansible.builtin.import_role:
+ name: "powerflex_webui"
+ vars:
+ powerflex_common_file_install_location: "/opt/aaab"
+ powerflex_webui_state: present
+ ignore_errors: true
+ register: powerflex_webui_install_config_wrong_path_result
+
+ - name: Verifying failure of install package with wrong file path
+ ansible.builtin.assert:
+ that:
+ - powerflex_common_package_file.files | length == 0
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/molecule.yml
new file mode 100644
index 000000000..93cad84c9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_installation_invalid_path_rpm/molecule.yml
@@ -0,0 +1,4 @@
+---
+scenario:
+ test_sequence:
+ - converge
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/converge.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/converge.yml
new file mode 100644
index 000000000..625f18a32
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/converge.yml
@@ -0,0 +1,48 @@
+---
+- name: Converge
+ hosts: webui
+ vars_files:
+ - ../../../../playbooks/roles/vars_files/connection.yml
+ gather_facts: true
+ tasks:
+ - name: Uninstall powerflex webui
+ ansible.builtin.import_role:
+ name: "powerflex_webui"
+ vars:
+ powerflex_webui_state: 'absent'
+
+ - name: Verifying uninstall package in converge
+ ansible.builtin.assert:
+ that:
+ - " 'Removed:' in powerflex_webui_uninstall_output.results[0].results[0]"
+ when: not ansible_check_mode and powerflex_webui_uninstall_output.changed and ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying uninstall package in check mode
+ ansible.builtin.assert:
+ that:
+ - powerflex_webui_uninstall_output.results[0].msg == "Check mode: No changes made, but would have if not in check mode"
+ when: ansible_check_mode and ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying uninstall package in Idempotency
+ ansible.builtin.assert:
+ that:
+ - powerflex_webui_uninstall_output.results[0].msg == 'Nothing to do'
+ when: not ansible_check_mode and not powerflex_webui_uninstall_output.changed and ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+ - name: Verifying uninstall package in check mode for deb
+ ansible.builtin.assert:
+ that:
+ - powerflex_webui_uninstall_deb_output.results[0].msg == "Check mode: No changes made, but would have if not in check mode"
+ when: ansible_check_mode and ansible_distribution == "Ubuntu"
+
+ - name: Verifying uninstall package in converge for deb
+ ansible.builtin.assert:
+ that:
+ - " 'Removed:' in powerflex_webui_uninstall_deb_output.results[0].results[0]"
+ when: not ansible_check_mode and powerflex_webui_uninstall_deb_output.changed and ansible_distribution == "Ubuntu"
+
+ - name: Verifying uninstall package in Idempotency for deb
+ ansible.builtin.assert:
+ that:
+ - powerflex_webui_uninstall_deb_output.results[0].msg == 'Nothing to do'
+ when: not ansible_check_mode and not powerflex_webui_uninstall_deb_output.changed and ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/molecule.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/molecule/webui_uninstallation/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/install_webui.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/install_webui.yml
new file mode 100644
index 000000000..13d58ffac
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/install_webui.yml
@@ -0,0 +1,23 @@
+---
+- name: Check if webui package is available
+ delegate_to: localhost
+ ansible.builtin.find:
+ paths: "{{ powerflex_common_file_install_location }}"
+ patterns: "*{{ file_glob_name }}*"
+
+- name: Get configured MDM IP addresses
+ dellemc.powerflex.mdm_cluster:
+ hostname: "{{ hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ state: present
+ register: powerflex_webui_result
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+- name: Set fact - powerflex_webui_mdm_ips
+ ansible.builtin.set_fact:
+ powerflex_webui_mdm_ips: "{{ powerflex_webui_result.mdm_cluster_details.mdmAddresses | join(',') }}"
+
+- name: Include install_powerflex.yml
+ ansible.builtin.include_tasks: ../../powerflex_common/tasks/install_powerflex.yml
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/main.yml
new file mode 100644
index 000000000..417f5d504
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- name: Install and Configure PowerFlex webUI
+ ansible.builtin.include_tasks: install_webui.yml
+ when: powerflex_webui_state == "present"
+
+- name: Uninstall PowerFlex webUI
+ ansible.builtin.include_tasks: uninstall_webui.yml
+ when: powerflex_webui_state == "absent"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/uninstall_webui.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/uninstall_webui.yml
new file mode 100644
index 000000000..72d7fd53a
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/tasks/uninstall_webui.yml
@@ -0,0 +1,20 @@
+---
+- name: Uninstall web UI package
+ register: powerflex_webui_uninstall_output
+ environment:
+ I_AM_SURE: "{{ i_am_sure | int }}"
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: "absent"
+ with_items:
+ - EMC-ScaleIO-mgmt-server
+ when: ansible_distribution in ("RedHat", "CentOS", "SLES")
+
+- name: Uninstall deb package
+ register: powerflex_webui_uninstall_deb_output
+ ansible.builtin.apt:
+ name: "{{ item }}"
+ state: absent
+ with_items:
+ - EMC-ScaleIO-mgmt-server
+ when: ansible_distribution == "Ubuntu"
diff --git a/ansible_collections/dellemc/powerflex/roles/powerflex_webui/vars/main.yml b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/vars/main.yml
new file mode 100644
index 000000000..aba9fecd1
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/roles/powerflex_webui/vars/main.yml
@@ -0,0 +1,5 @@
+---
+file_glob_name: mgmt-server
+powerflex_role_environment:
+ MDM_IP: "{{ powerflex_webui_mdm_ips }}"
+file_gpg_name: RPM-GPG-KEY-ScaleIO