summaryrefslogtreecommitdiffstats
path: root/ansible_collections/dellemc/openmanage/roles
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:22 +0000
commit38b7c80217c4e72b1d8988eb1e60bb6e77334114 (patch)
tree356e9fd3762877d07cde52d21e77070aeff7e789 /ansible_collections/dellemc/openmanage/roles
parentAdding upstream version 7.7.0+dfsg. (diff)
downloadansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.tar.xz
ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.zip
Adding upstream version 9.4.0+dfsg.upstream/9.4.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--ansible_collections/dellemc/openmanage/roles/README.md22
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/README.md308
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/defaults/main.yml5
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/argument_specs.yml71
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/main.yml25
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/converge.yml306
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/molecule.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/cleanup.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/converge.yml32
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/molecule.yml (renamed from ansible_collections/dellemc/os10/tests/integration/targets/os10_ntp_role/tests/ntp_basic.yaml)0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/cleanup.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/converge.yml32
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/cleanup.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/converge.yml32
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/tasks/main.yml16
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/tests/inventory (renamed from ansible_collections/dellemc/os6/roles/os6_ntp/tests/inventory)0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_attributes/vars/main.yml3
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/README.md368
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/defaults/main.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/argument_specs.yml122
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/main.yml25
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/__get_data.yml16
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/prepare.yml62
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/converge.yml135
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/molecule.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/converge.yml159
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/molecule.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/converge.yml32
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/molecule.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/converge.yml35
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/molecule.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/cleanup.yml17
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/prepare.yml30
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/converge.yml54
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/molecule.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/converge.yml60
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/molecule.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/converge.yml50
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/molecule.yml14
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/converge.yml74
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/molecule.yml14
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/converge.yml74
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/molecule.yml14
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/tasks/main.yml67
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/tests/inventory (renamed from ansible_collections/dellemc/os6/roles/os6_qos/tests/inventory)0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_bios/vars/main.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/README.md373
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/defaults/main.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/argument_specs.yml133
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/main.yml26
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/converge.yml119
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/converge.yml119
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/converge.yml120
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/converge.yml120
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/converge.yml102
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/converge.yml102
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/converge.yml102
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/converge.yml116
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/converge.yml129
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/converge.yml311
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/molecule.yml9
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/tasks/main.yml27
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_boot/vars/main.yml3
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/README.md386
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/defaults/main.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/argument_specs.yml132
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/main.yml22
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/converge.yml90
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/converge.yml168
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/converge.yml90
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/converge.yml207
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/converge.yml90
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/converge.yml94
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__delete_directory.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__extract_firmware_version.yml21
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_helper.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_ssl_key.yml18
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/converge.yml381
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/converge.yml56
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/converge.yml31
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/export.yml14
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/generate_csr.yml24
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/import.yml18
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/main.yml18
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/reset.yml16
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/inventory1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_certificate/vars/main.yml3
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/README.md361
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/defaults/main.yml15
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/argument_specs.yml143
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/main.yml53
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/cleanup.yml96
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/converge.yml100
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/molecule.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/verify.yml115
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/main.yml24
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/pre_req.yml13
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_cifs.yml21
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_http.yml27
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_https.yml28
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_local.yml19
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_nfs.yml19
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/vars/main.yml4
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/README.md342
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/defaults/main.yml11
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/argument_specs.yml114
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/main.yml20
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/converge.yml101
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/converge.yml117
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/converge.yml206
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/converge.yml37
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/tasks/main.yml27
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_firmware/vars/main.yml3
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/README.md767
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/defaults/main.yml8
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/argument_specs.yml110
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/main.yml22
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/converge.yml44
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/converge.yml81
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/converge.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/converge.yml45
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/converge.yml95
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/converge.yml44
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/converge.yml38
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/converge.yml38
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/converge.yml44
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/converge.yml93
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/converge.yml44
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/converge.yml92
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/converge.yml44
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/converge.yml44
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/converge.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/converge.yml80
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/converge.yml79
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/converge.yml65
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/converge.yml105
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_attributes_info.yml28
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_backplane_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_battery_info.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_bios_info.yml13
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_controller_info.yml38
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_cpu_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_emm_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_fan_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_firmware_info.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_host_nic_info.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_intrusion_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_license_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_memory_info.yml13
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_metrics_info.yml93
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_nic_info.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pas_sensor_info.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pcie_device_info.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_physical_info.yml24
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_power_supply_info.yml13
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_resource_id.yml60
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_secure_boot_info.yml41
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_system_info.yml19
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_virtual_disk_info.yml25
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_voltage_info.yml12
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/main.yml81
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/backplane_assert.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/controller_assert.yml70
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/cpu_assert.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosure_assert.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosureemm_assert.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/fan_assert.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/firmware_assert.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/hostnic_assert.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/lc_assert.yml28
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/license_assert.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/manager_assert.yml28
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/memory_assert.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/mmetrics_assert.yml38
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/nic_assert.yml40
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/passensor_assert.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/pciedevice_assert.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/physicaldisk_assert.yml45
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/powersupply_assert.yml42
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/psmetrics_assert.yml29
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/secureboot_assert.yml62
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/sensorsvoltage_assert.yml20
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/system_assert.yml28
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/tmetrics_assert.yml20
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/virtualdisk_assert.yml45
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/vars/main.yml46
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/README.md393
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/defaults/main.yml15
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/argument_specs.yml138
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/main.yml53
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/converge.yml313
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/molecule.yml9
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/converge.yml39
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/converge.yml37
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/converge.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/converge.yml36
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/converge.yml35
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/converge.yml41
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/converge.yml38
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/prepare.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/resources/tests/prepare.yml18
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tasks/main.yml31
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/test.yml5
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/vars/main.yml4
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/README.md181
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/defaults/main.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/argument_specs.yml53
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/main.yml28
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/converge.yml112
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/converge.yml90
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/converge.yml91
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/molecule.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_api.yml66
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_wsman.yml70
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/delete_job_with_id.yml41
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/get_idrac_firmware_version.yml20
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/main.yml53
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/validate_input_data.yml73
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue.j225
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue_force.j225
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_job_queue/vars/main.yml30
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/README.md509
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/esxi.yml20
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/main.yml9
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/rhel.yml16
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/argument_specs.yml191
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/main.yml19
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_destinations.yml25
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_working_directory.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/copy_iso_to_destination.yml60
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/create_working_directory_path.yml28
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/download_or_copy_source_files.yml112
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/validate_inputs.yml74
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/esxi/compile_iso.yml37
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/attach_iso_to_virtual_media.yml43
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/clean_up_virtual_media_slot.yml13
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/set_boot_mode_and_restart.yml15
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/extract_iso.yml15
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/generate_kickstart_file.yml15
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/main.yml74
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/rhel/compile_iso.yml73
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/tracking/track_for_os_deployment.yml11
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/ESXI_8.j239
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_8.j231
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_9.j231
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/inventory8
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/test.yml5
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/vars/main.yml93
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/README.md180
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/defaults/main.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/argument_specs.yml70
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/main.yml25
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/lcstatus_check.yml95
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/main.yml146
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/templates/idrac_lifecycle_controller_status.j223
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_reset/vars/main.yml41
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/README.md217
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/defaults/main.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/argument_specs.yml69
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/main.yml54
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/converge.yml188
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/molecule.yml9
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/converge.yml69
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/converge.yml72
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/converge.yml72
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/converge.yml63
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/converge.yml72
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/converge.yml73
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/converge.yml72
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/converge.yml48
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/init.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/main.yml18
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/vars/main.yml3
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/README.md682
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/defaults/main.yml7
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/argument_specs.yml200
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/main.yml26
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tasks/main.yml200
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/vars/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/molecule.yml37
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/README.md219
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/defaults/main.yml9
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/argument_specs.yml60
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/main.yml55
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/converge.yml74
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/molecule.yml15
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/converge.yml174
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/molecule.yml15
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/cleanup.yml16
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/prepare.yml17
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/tasks/main.yml16
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/test.yml5
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_firmware/vars/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/README.md417
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/defaults/main.yml10
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/handlers/main.yml2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/argument_specs.yml176
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/main.yml22
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/converge.yml83
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/converge.yml83
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/converge.yml83
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/converge.yml83
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/converge.yml83
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/converge.yml80
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/converge.yml80
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__delete_virtual_drive.yml33
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__extract_storage.yml27
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__get_helper.yml22
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__idrac_reset.yml23
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__lc_status.yml22
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/converge.yml156
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/converge.yml133
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/converge.yml157
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/converge.yml157
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/molecule.yml1
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/converge.yml132
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/converge.yml55
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/molecule.yml0
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tasks/main.yml34
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/inventory2
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/test.yml6
-rw-r--r--ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/vars/main.yml4
466 files changed, 22439 insertions, 0 deletions
diff --git a/ansible_collections/dellemc/openmanage/roles/README.md b/ansible_collections/dellemc/openmanage/roles/README.md
new file mode 100644
index 000000000..90f2f97d5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/README.md
@@ -0,0 +1,22 @@
+# dellemc.openmanage roles directory
+
+Here are the list of roles supported by Dell.
+
+```
+.
+├── idrac_attributes
+├── idrac_bios
+├── idrac_boot
+├── idrac_certificate
+├── idrac_export_server_config_profile
+├── idrac_firmware
+├── idrac_gather_facts
+├── idrac_import_server_config_profile
+├── idrac_job_queue
+├── idrac_os_deployment
+├── idrac_reset
+├── idrac_server_powerstate
+├── idrac_storage_controller
+├── redfish_firmware
+└── redfish_storage_volume
+``` \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/README.md
new file mode 100644
index 000000000..2458b1ab5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/README.md
@@ -0,0 +1,308 @@
+# idrac_attributes
+
+Role to configure the iDRAC system, manager and lifecycle attributes for Dell PowerEdge servers.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address or hostname.</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username with admin privileges</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>idrac_attributes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- Dictionary of iDRAC attributes and value. The attributes should be part of the Integrated Dell Remote Access Controller Attribute Registry.<br>- To view the list of attributes in Attribute Registry for iDRAC9 and above, use the Role idrac_gather_facts with idrac components.<br>- For iDRAC8 based servers, derive the manager attribute name from Server Configuration Profile.<br>- If the manager attribute name in Server Configuration Profile is <GroupName><Instance>#<AttributeName>(for Example, 'SNMP.1#AgentCommunity') then the equivalent attribute name for Redfish is <GroupName>.<Instance>.<AttributeName> (for Example, 'SNMP.1.AgentCommunity').</td>
+ </tr>
+ <tr>
+ <td>system_attributes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- Dictionary of System attributes and value. The attributes should be part of the Integrated Dell Remote Access Controller Attribute Registry.<br>- To view the list of attributes in Attribute Registry for iDRAC9 and above, use the Role idrac_gather_facts with idrac components.<br>- For iDRAC8 based servers, derive the manager attribute name from Server Configuration Profile.<br>- If the manager attribute name in Server Configuration Profile is <GroupName><Instance>#<AttributeName> for Example, 'ThermalSettings.1#ThermalProfile') then the equivalent attribute name for Redfish is <GroupName>.<Instance>.<AttributeName> (for Example, 'ThermalSettings.1.ThermalProfile').</td>
+ </tr>
+ <tr>
+ <td>lifecycle_controller_attributes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- Dictionary of Lifecycle Controller attributes and value. The attributes should be part of the Integrated Dell Remote Access Controller Attribute Registry.<br>- To view the list of attributes in Attribute Registry for iDRAC9 and above, use the Role idrac_gather_facts with idrac components.<br>- For iDRAC8 based servers, derive the manager attribute name from Server Configuration Profile.<br>- If the manager attribute name in Server Configuration Profile is <GroupName>.<Instance>#<AttributeName>(for Example, 'LCAttributes.1#AutoUpdate') then the equivalent attribute name for Redfish is <GroupName>.<Instance>.<AttributeName>(for Example, 'LCAttributes.1.AutoUpdate')</td>
+ <tr>
+ <td>manager_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Redfish ID of the resource. If the Redfish ID of the resource is not specified, then the first ID from the Manager IDs list will be picked up.</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_attributes_out</td>
+ <td>{"changed": true,
+ "failed": false,
+ "msg": "Successfully updated the attributes."
+}</td>
+<td>Module output of idrac attributes</td>
+</tbody>
+</table>
+
+## Examples
+-----
+
+```
+- name: Configure iDRAC attributes
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ SNMP.1.AgentCommunity: public
+
+- name: Configure System attributes
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ system_attributes:
+ ThermalSettings.1.ThermalProfile: Sound Cap
+
+- name: Configure Lifecycle Controller attributes
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ lifecycle_controller_attributes:
+ LCAttributes.1.AutoUpdate: Enabled
+
+- name: Configure the iDRAC attributes for email alert settings.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ EmailAlert.1.CustomMsg: Display Message
+ EmailAlert.1.Enable: Enabled
+ EmailAlert.1.Address: test@test.com
+
+- name: Configure the iDRAC attributes for SNMP alert settings.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ SNMPAlert.1.Destination: 192.168.0.2
+ SNMPAlert.1.State: Enabled
+ SNMPAlert.1.SNMPv3Username: username
+
+- name: Configure the iDRAC attributes for SMTP alert settings.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ RemoteHosts.1.SMTPServerIPAddress: 192.168.0.3
+ RemoteHosts.1.SMTPAuthentication: Enabled
+ RemoteHosts.1.SMTPPort: 25
+ RemoteHosts.1.SMTPUserName: username
+ RemoteHosts.1.SMTPPassword: password
+
+- name: Configure the iDRAC attributes for webserver settings.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ WebServer.1.SSLEncryptionBitLength: 128-Bit or higher
+ WebServer.1.TLSProtocol: TLS 1.1 and Higher
+
+- name: Configure the iDRAC attributes for SNMP settings.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ SNMP.1.SNMPProtocol: All
+ SNMP.1.AgentEnable: Enabled
+ SNMP.1.TrapFormat: SNMPv1
+ SNMP.1.AlertPort: 162
+ SNMP.1.AgentCommunity: public
+
+- name: Configure the iDRAC LC attributes for collecting system inventory.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ lifecycle_controller_attributes:
+ LCAttributes.1.CollectSystemInventoryOnRestart: Enabled
+
+- name: Configure the iDRAC system attributes for LCD configuration.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ system_attributes:
+ LCD.1.Configuration: Service Tag
+ LCD.1.vConsoleIndication: Enabled
+ LCD.1.FrontPanelLocking: Full-Access
+ LCD.1.UserDefinedString: custom string
+
+- name: Configure the iDRAC attributes for Timezone settings.
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ Time.1.Timezone: CST6CDT
+ NTPConfigGroup.1.NTPEnable: Enabled
+ NTPConfigGroup.1.NTP1: 192.168.0.5
+ NTPConfigGroup.1.NTP2: 192.168.0.6
+ NTPConfigGroup.1.NTP3: 192.168.0.7
+
+- name: Configure all attributes
+ ansible.builtin.include_role:
+ name: idrac_attributes
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ idrac_attributes:
+ SNMP.1.AgentCommunity: test
+ SNMP.1.AgentEnable: Enabled
+ SNMP.1.DiscoveryPort: 161
+ system_attributes:
+ ServerOS.1.HostName: demohostname
+ lifecycle_controller_attributes:
+ LCAttributes.1.AutoUpdate: Disabled
+```
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Kritika Bhateja (Kritika.Bhateja@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/defaults/main.yml
new file mode 100644
index 000000000..60830a744
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+# defaults file for idrac_attributes
+validate_certs: true
+https_timeout: 30
+https_port: 443
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/handlers/main.yml
new file mode 100644
index 000000000..ed09341c4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_attributes
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/argument_specs.yml
new file mode 100644
index 000000000..2109b32a0
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/argument_specs.yml
@@ -0,0 +1,71 @@
+---
+argument_specs:
+ main:
+ version_added: "7.6.0"
+ short_description: Role to configure the iDRAC attribute
+ description:
+ - Role to configure the iDRAC system, manager and lifecycle attributes for Dell PowerEdge servers.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address or hostname.
+ username:
+ type: str
+ description: iDRAC username with admin privileges.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The HTTPS socket level timeout in seconds.
+ type: int
+ default: 30
+ idrac_attributes:
+ description:
+ - Dictionary of iDRAC attributes and value. The attributes should be part of the
+ Integrated Dell Remote Access Controller Attribute Registry.
+ - To view the list of attributes in Attribute Registry for iDRAC9 and above, use
+ the Role idrac_gather_facts with idrac components.
+ - For iDRAC8 based servers, derive the manager attribute name from Server Configuration Profile.
+ - If the manager attribute name in Server Configuration Profile is <GroupName>.<Instance>#<AttributeName>
+ (for Example, 'SNMP.1#AgentCommunity') then the equivalent attribute name for Redfish is <GroupName>.
+ <Instance>.<AttributeName> (for Example, 'SNMP.1.AgentCommunity').
+ type: dict
+ system_attributes:
+ description:
+ - Dictionary of System attributes and value. The attributes should be part of the Integrated Dell Remote Access Controller Attribute Registry.
+ - To view the list of attributes in Attribute Registry for iDRAC9 and above, use the Role idrac_gather_facts with idrac components
+ - For iDRAC8 based servers, derive the manager attribute name from Server Configuration Profile.
+ - If the manager attribute name in Server Configuration Profile is <GroupName>.<Instance>#<AttributeName>
+ (for Example, 'ThermalSettings.1#ThermalProfile') then the equivalent attribute name for Redfish is <GroupName>.<Instance>.<AttributeName>
+ (for Example, 'ThermalSettings.1.ThermalProfile').
+ type: dict
+ lifecycle_controller_attributes:
+ description:
+ - Dictionary of Lifecycle Controller attributes and value. The attributes should be part of the
+ Integrated Dell Remote Access Controller Attribute Registry.
+ - To view the list of attributes in Attribute Registry for iDRAC9 and above, use the Role idrac_gather_facts with idrac components
+ - For iDRAC8 based servers, derive the manager attribute name from Server Configuration Profile.
+ - If the manager attribute name in Server Configuration Profile is <GroupName>.<Instance>#<AttributeName>
+ (for Example, 'LCAttributes.1#AutoUpdate') then the equivalent attribute name for Redfish is <GroupName>.<Instance>.<AttributeName>
+ (for Example, 'LCAttributes.1.AutoUpdate')."
+ type: dict
+ manager_id:
+ description:
+ Redfish ID of the resource. If the Redfish ID of the resource is not specified, then the first ID from the Manager IDs list
+ will be picked up.
+ type: str
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/main.yml
new file mode 100644
index 000000000..737f01569
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/meta/main.yml
@@ -0,0 +1,25 @@
+galaxy_info:
+ role_name: idrac_attributes
+ author: "Kritika Bhateja"
+ description: The role helps to configure the iDRAC system, manager and lifecycle attributes for Dell PowerEdge servers.
+ company: Dell Technologies
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.13"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/converge.yml
new file mode 100644
index 000000000..f1ae0f548
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/converge.yml
@@ -0,0 +1,306 @@
+---
+- name: Converge file for default/negative scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Perform update with wrong hostname
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "randomHostname"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ idrac_attributes:
+ SSH.1.Timeout: 1800
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with wrong hostname
+ ansible.builtin.assert:
+ that:
+ - "'Incorrect username or password,
+ unreachable iDRAC IP' in '{{ idrac_attributes_out.msg }}' or
+ 'Name or service not known' in '{{ idrac_attributes_out.msg }}'"
+
+ - name: Perform update with wrong username
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "WrongUsername123"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ idrac_attributes:
+ SSH.1.Timeout: 1800
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with wrong username
+ ansible.builtin.assert:
+ that:
+ - '"HTTP Error 401" in idrac_attributes_out.msg'
+
+ - name: Perform update with wrong password
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "WrongPassword@123"
+ validate_certs: false
+ idrac_attributes:
+ SSH.1.Timeout: 1800
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with wrong password
+ ansible.builtin.assert:
+ that: |-
+ ('"HTTP Error 401" in idrac_attributes_out.msg')
+ or
+ ('"urlopen error timed out" in idrac_attributes_out.msg')
+
+ - name: Perform update with invalid https_port
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ https_port: 9999999
+ idrac_attributes:
+ SSH.1.Timeout: 1800
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with invalid https_port
+ ansible.builtin.assert:
+ that:
+ - ('"Connection refused" in idrac_attributes_out.msg')
+ or
+ ('"urlopen error timed out" in idrac_attributes_out.msg')
+
+ - name: Perform update with invalid validate_certs
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: "someStringValue"
+ idrac_attributes:
+ SSH.1.Timeout: 1800
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with invalid validate_certs
+ ansible.builtin.assert:
+ that:
+ - '"Valid booleans include" in idrac_attributes_out.msg'
+
+ - name: Perform update with wrong ca_path
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ ca_path: ""
+ validate_certs: true
+ idrac_attributes:
+ SSH.1.Timeout: 1800
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with wrong ca_path
+ ansible.builtin.assert:
+ that:
+ - '"certificate verify failed" in idrac_attributes_out.msg'
+
+ - name: Perform update with wrong manager_id
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ idrac_attributes:
+ SSH.1.Timeout: 1800
+ manager_id: idrac.random.5
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with wrong manager_id
+ ansible.builtin.assert:
+ that:
+ - '"HTTP Error 404" in idrac_attributes_out.msg'
+
+ - name: Perform update with read only attributes
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ idrac_attributes:
+ SSH.1.MaxSessions: 5
+ manager_id: "{{ null | default(omit) }}"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with read only attributes
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Attributes have invalid values."
+
+ - name: Perform idrac_attributes update with invalid attributes
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ idrac_attributes:
+ invalidAttr: enabled
+ manager_id: "{{ null | default(omit) }}"
+ ignore_errors: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with invalid attributes
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Attributes have invalid values."
+
+ - name: Perform idrac_attributes update with
+ valid attributes and invalid values
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ idrac_attributes:
+ SSH.1.Timeout: false
+ manager_id: "{{ null | default(omit) }}"
+ ignore_errors: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation with
+ valid attributes and invalid values
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Attributes have invalid values."
+
+ - name: Perform system_attributes update with invalid attributes
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ system_attributes:
+ invalidAttr: enabled
+ idrac_attributes: "{{ null | default(omit) }}"
+ manager_id: "{{ null | default(omit) }}"
+ ignore_errors: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation for system_attributes
+ with invalid attributes
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Attributes have invalid values."
+
+ - name: Perform system_attributes update with
+ valid attributes and invalid values
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ system_attributes:
+ Job.1.JobTimeout: stringValue
+ manager_id: "{{ null | default(omit) }}"
+ idrac_attributes: "{{ null | default(omit) }}"
+ ignore_errors: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation for system_attributes
+ with valid attributes and invalid values
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Attributes have invalid values."
+
+ - name: Perform lifecycle_controller_attributes update
+ with invalid attributes
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ lifecycle_controller_attributes:
+ invalidAttr: false
+ idrac_attributes: "{{ null | default(omit) }}"
+ system_attributes: "{{ null | default(omit) }}"
+ manager_id: "{{ null | default(omit) }}"
+ ignore_errors: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation for
+ lifecycle_controller_attributes with invalid attributes
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Attributes have invalid values."
+
+ - name: Perform lifecycle_controller_attributes update with
+ valid attributes and invalid values
+ ansible.builtin.import_role:
+ name: idrac_attributes
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ https_port: 443
+ validate_certs: false
+ lifecycle_controller_attributes:
+ LCAttributes.1.AutoUpdate: 12345
+ manager_id: "{{ null | default(omit) }}"
+ idrac_attributes: "{{ null | default(omit) }}"
+ system_attributes: "{{ null | default(omit) }}"
+ ignore_errors: true
+ register: idrac_attributes_error_msg
+
+ - name: Asserting after performing operation for
+ lifecycle_controller_attributes with
+ valid attributes and invalid values
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Attributes have invalid values."
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/molecule.yml
new file mode 100644
index 000000000..210914970
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/default/molecule.yml
@@ -0,0 +1,6 @@
+---
+scenario:
+ test_sequence:
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/cleanup.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/cleanup.yml
new file mode 100644
index 000000000..58b3846e3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/cleanup.yml
@@ -0,0 +1,12 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_to_default: Default
+ roles:
+ - role: idrac_reset
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/converge.yml
new file mode 100644
index 000000000..a116aad93
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/converge.yml
@@ -0,0 +1,32 @@
+---
+- name: Converge file for idrac_attributes
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ roles:
+ - role: idrac_attributes
+ vars:
+ idrac_attributes:
+ SSH.1.Timeout: 1700
+ tasks:
+ - name: Asserting idrac_attributes update in check mode
+ ansible.builtin.assert:
+ that: idrac_attributes_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting idrac_attributes update in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Successfully updated the attributes."
+ when: not ansible_check_mode and idrac_attributes_out.changed
+
+ - name: Asserting idrac_attributes update in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_attributes_out.changed
diff --git a/ansible_collections/dellemc/os10/tests/integration/targets/os10_ntp_role/tests/ntp_basic.yaml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/molecule.yml
index ed97d539c..ed97d539c 100644
--- a/ansible_collections/dellemc/os10/tests/integration/targets/os10_ntp_role/tests/ntp_basic.yaml
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/idrac_attr/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/cleanup.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/cleanup.yml
new file mode 100644
index 000000000..58b3846e3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/cleanup.yml
@@ -0,0 +1,12 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_to_default: Default
+ roles:
+ - role: idrac_reset
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/converge.yml
new file mode 100644
index 000000000..b9e7b2124
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/converge.yml
@@ -0,0 +1,32 @@
+---
+- name: Converge file for lifecycle_controller_attributes
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ roles:
+ - role: idrac_attributes
+ vars:
+ lifecycle_controller_attributes:
+ LCAttributes.1.AutoUpdate: Enabled
+ tasks:
+ - name: Asserting lifecycle_controller_attributes update in check mode
+ ansible.builtin.assert:
+ that: idrac_attributes_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting lifecycle_controller_attributes update in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Successfully updated the attributes."
+ when: not ansible_check_mode and idrac_attributes_out.changed
+
+ - name: Asserting lifecycle_controller_attributes update in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_attributes_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/lifecycle_controller_attr/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/cleanup.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/cleanup.yml
new file mode 100644
index 000000000..58b3846e3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/cleanup.yml
@@ -0,0 +1,12 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_to_default: Default
+ roles:
+ - role: idrac_reset
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/converge.yml
new file mode 100644
index 000000000..ae59956e7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/converge.yml
@@ -0,0 +1,32 @@
+---
+- name: Converge file for system_attributes
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ roles:
+ - role: idrac_attributes
+ vars:
+ system_attributes:
+ ServerOS.1.HostName: demohostname
+ tasks:
+ - name: Asserting system_attributes update in check mode
+ ansible.builtin.assert:
+ that: idrac_attributes_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting system_attributes update in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "Successfully updated the attributes."
+ when: not ansible_check_mode and idrac_attributes_out.changed
+
+ - name: Asserting system_attributes update in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_attributes_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_attributes_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/molecule/system_attr/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tasks/main.yml
new file mode 100644
index 000000000..80bc1edb4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- name: Configure attributes
+ dellemc.openmanage.idrac_attributes:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ idrac_attributes: "{{ idrac_attributes | default(omit) }}"
+ system_attributes: "{{ system_attributes | default(omit) }}"
+ lifecycle_controller_attributes: "{{ lifecycle_controller_attributes | default(omit) }}"
+ resource_id: "{{ manager_id | default(omit) }}"
+ timeout: "{{ https_timeout }}"
+ register: idrac_attributes_out
+ delegate_to: "{{ idrac_attributes_delegate }}"
diff --git a/ansible_collections/dellemc/os6/roles/os6_ntp/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tests/inventory
index 878877b07..878877b07 100644
--- a/ansible_collections/dellemc/os6/roles/os6_ntp/tests/inventory
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tests/inventory
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tests/test.yml
new file mode 100644
index 000000000..0016e133a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Tests for idrac attributes
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_attributes
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_attributes/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/vars/main.yml
new file mode 100644
index 000000000..9684f674f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_attributes/vars/main.yml
@@ -0,0 +1,3 @@
+---
+# vars file for idrac_attributes
+idrac_attributes_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_bios/README.md
new file mode 100644
index 000000000..25f439dc2
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/README.md
@@ -0,0 +1,368 @@
+# idrac_bios
+
+This role allows to modify BIOS attributes, clear pending BIOS attributes, and reset the BIOS to default settings.
+
+## Requirements
+
+---
+
+Requirements to develop and contribute to the role.
+
+### Development
+
+```text
+ansible
+docker
+molecule
+python
+```
+
+### Production
+
+Requirements to use the role.
+
+```text
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```text
+dellemc.openmanage
+```
+
+## Role Variables
+
+---
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC user password</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>iDRAC port</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ </td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>The socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>attributes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>
+ - "Dictionary of BIOS attributes and value pair. Attributes should be part of the Redfish Dell BIOS Attribute Registry. Use U(https://I(idrac_ip)/redfish/v1/Systems/System.Embedded.1/Bios) to view the Redfish URI." <br>
+ - This is mutually exclusive with I(reset_bios).
+ </td>
+ </tr>
+ <tr>
+ <td>apply_time</td>
+ <td>false</td>
+ <td>Immediate</td>
+ <td>Immediate, OnReset, AtMaintenanceWindowStart, InMaintenanceWindowOnReset</td>
+ <td>str</td>
+ <td>
+ - Apply time of the I(attributes). <br>
+ - This is applicable only to I(attributes). <br>
+ - C(Immediate) Allows the user to immediately reboot the host and apply the changes.
+ I(job_wait) is applicable. <br>
+ - C(OnReset) Allows the user to apply the changes on the next reboot of the host server. <br>
+ - C(AtMaintenanceWindowStart) Allows the user to apply the changes at the start of a maintenance window as specifiedin
+ I(maintenance_window). A reboot job will be scheduled. <br>
+ - C(InMaintenanceWindowOnReset) Allows to apply the changes after a manual reset but within the maintenance window as specified in
+ I(maintenance_window).
+ </td>
+ </tr>
+ <tr>
+ <td>maintenance_window</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>
+ - Option to schedule the maintenance window. <br>
+ - This is required when I(apply_time) is C(AtMaintenanceWindowStart) or
+ C(InMaintenanceWindowOnReset).
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start_time</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>
+ - The start time for the maintenance window to be scheduled. <br>
+ - The format is YYYY-MM-DDThh:mm:ss<offset>, <offset> is the time offset from UTC that
+ the current time zone set in iDRAC in the format: +05:30 for IST.
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duration</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>int</td>
+ <td>
+ - The duration in seconds for the maintenance window. <br>
+ </td>
+ </tr>
+ <tr>
+ <td>clear_pending</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>
+ - Allows the user to clear all pending BIOS attributes changes. <br>
+ - C(true) discards any pending changes to BIOS attributes or removes the job if in
+ scheduled state. <br>
+ - This operation will not create any job. <br>
+ - C(false) does not perform any operation. <br>
+ - This is mutually exclusive with I(reset_bios). <br>
+ - C(Note) Any BIOS job scheduled will not be cleared because of boot sources configuration. <br>
+ </td>
+</tr>
+ <tr>
+ <td>reset_bios</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>
+ - Resets the BIOS to default settings and triggers a reboot of host system. <br>
+ - This is applied to the host after the restart. <br>
+ - This operation will not create any job. <br>
+ - C(false) does not perform any operation. <br>
+ - This is mutually exclusive with I(attributes), and I(clear_pending). <br>
+ - When C(true), this action will always report as changes found to be applicable.
+ </td>
+ </tr>
+ <tr>
+ <td>reset_type</td>
+ <td>false</td>
+ <td>graceful_restart</td>
+ <td>graceful_restart <br> force_restart</td>
+ <td>str</td>
+ <td>
+ - C(force_restart) Forcefully reboot the host system. <br>
+ - C(graceful_restart) Gracefully reboot the host system. <br>
+ - This is applicable for I(reset_bios), and I(attributes) when I(apply_time) is
+ C(Immediate).
+ </td>
+ </tr>
+ <tr>
+ <td>job_wait</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>
+ - Provides the option to wait for job completion. <br>
+ - This is applicable for I(attributes) when I(apply_time) is C(Immediate). <br>
+ </td>
+ </tr>
+ <tr>
+ <td>job_wait_timeout</td>
+ <td>false</td>
+ <td>1200</td>
+ <td></td>
+ <td>int</td>
+ <td>
+ - The maximum wait time of I(job_wait) in seconds. <br>
+ The job is tracked only for this duration. <br>
+ - This option is applicable when I(job_wait) is C(True). <br>
+ </td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_bios_out</td>
+ <td>{
+ "attributes": {
+ "ansible_facts": {},
+ "changed": true,
+ "failed": false,
+ "job_id": "JID_XXXXXXXXXXXX",
+ "msg": {
+ "ActualRunningStartTime": "2023-05-19T04:55:01",
+ "ActualRunningStopTime": "2023-05-19T04:59:21",
+ "CompletionTime": "2023-05-19T04:59:21",
+ "Description": "Job Instance",
+ "EndTime": "TIME_NA",
+ "Id": "JID_844899049402",
+ "JobState": "Completed",
+ "JobType": "BIOSConfiguration",
+ "Message": "Job completed successfully.",
+ "MessageArgs": [],
+ "MessageId": "PR19",
+ "Name": "Configure: BIOS.Setup.1-1",
+ "PercentComplete": 100,
+ "StartTime": "2023-05-19T04:51:44",
+ "TargetSettingsURI": null
+ },
+ "status_msg": "Successfully applied the BIOS attributes update."
+ },
+ "clear_pending": {
+ "changed": false,
+ "skip_reason": "Conditional result was False",
+ "skipped": true
+ },
+ "reset_bios": {
+ "changed": false,
+ "skip_reason": "Conditional result was False",
+ "skipped": true
+ }
+}</td>
+ <td>Module output of the idrac_bios job.</td>
+ </tr>
+ </tbody>
+</table>
+
+## Examples
+
+---
+
+```yaml
+- name: Configure generic attributes of the BIOS
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ attributes:
+ BootMode : "Bios"
+ OneTimeBootMode: "Enabled"
+ BootSeqRetry: "Enabled"
+```
+
+```yaml
+- name: Configure BIOS attributes at Maintenance window.
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ start_time: "2022-09-30T05:15:40-05:00"
+ duration: 600
+ attributes:
+ BootMode : "Bios"
+ OneTimeBootMode: "Enabled"
+ BootSeqRetry: "Enabled"
+```
+
+```yaml
+- name: Clear pending BIOS attributes.
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ clear_pending: true
+```
+
+```yaml
+- name: Reset BIOS attributes to default settings.
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_bios: true
+```
+
+## Author Information
+
+---
+
+Dell Technologies <br>
+Abhishek Sinha (Abhishek.Sinha10@Dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/defaults/main.yml
new file mode 100644
index 000000000..6b146abc8
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/defaults/main.yml
@@ -0,0 +1,10 @@
+---
+# defaults file for idrac_bios
+https_port: 443
+validate_certs: true
+https_timeout: 30
+apply_time: "Immediate"
+clear_pending: false
+reset_type: "graceful_restart"
+job_wait: true
+job_wait_timeout: 1200
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/handlers/main.yml
new file mode 100644
index 000000000..7cbf8c33d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_bios
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/argument_specs.yml
new file mode 100644
index 000000000..febdd96ca
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/argument_specs.yml
@@ -0,0 +1,122 @@
+---
+argument_specs:
+ main:
+ version_added: "7.6.0"
+ short_description: Modify and clear BIOS attributes, and reset BIOS settings
+ description:
+ - This role allows to modify BIOS attributes, clear pending BIOS attributes, and reset the BIOS to default settings.
+ options:
+ hostname:
+ required: true
+ type: str
+ description:
+ - iDRAC IP Address.
+ username:
+ type: str
+ description:
+ - iDRAC username.
+ password:
+ type: str
+ description:
+ - iDRAC user password.
+ https_port:
+ type: int
+ description:
+ - iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description:
+ - The socket level timeout in seconds.
+ type: int
+ default: 30
+ attributes:
+ type: dict
+ description:
+ - Dictionary of BIOS attributes and value pair.
+ Attributes should be part of the Redfish Dell BIOS Attribute Registry.
+ Use idrac_gather_facts role to fetch the BIOS attributes.
+ - This is mutually exclusive with I(reset_bios).
+ apply_time:
+ description:
+ - Apply time of the I(attributes).
+ - This is applicable only to I(attributes).
+ - C(Immediate) Allows the user to immediately reboot the host and apply the changes. I(job_wait) is applicable.
+ - C(OnReset) Allows the user to apply the changes on the next reboot of the host server.
+ - C(AtMaintenanceWindowStart) Allows the user to apply the changes at the start of a maintenance window as specified in
+ I(maintenance_window). A reboot job will be scheduled.
+ - C(InMaintenanceWindowOnReset) Allows to apply the changes after a manual reset but within the maintenance window as specified in
+ I(maintenance_window).
+ choices:
+ [
+ Immediate,
+ OnReset,
+ AtMaintenanceWindowStart,
+ InMaintenanceWindowOnReset,
+ ]
+ default: Immediate
+ maintenance_window:
+ type: dict
+ description:
+ - Option to schedule the maintenance window.
+ - This is required when I(apply_time) is C(AtMaintenanceWindowStart) or C(InMaintenanceWindowOnReset).
+ options:
+ start_time:
+ type: str
+ description:
+ - The start time for the maintenance window to be scheduled.
+ - "The format is YYYY-MM-DDThh:mm:ss<offset>"
+ - "<offset> is the time offset from UTC that the current time zone set in iDRAC in the format: +05:30 for IST."
+ required: true
+ duration:
+ type: int
+ description:
+ - The duration in seconds for the maintenance window.
+ required: true
+ clear_pending:
+ type: bool
+ description:
+ - Allows the user to clear all pending BIOS attributes changes.
+ - C(true) discards any pending changes to BIOS attributes or removes the job if in scheduled state.
+ - This operation will not create any job.
+ - C(false) does not perform any operation.
+ - This is mutually exclusive with I(boot_sources), I(attributes), and I(reset_bios).
+ - C(Note) Any BIOS job scheduled will not be cleared because of boot sources configuration.
+ reset_bios:
+ type: bool
+ description:
+ - Resets the BIOS to default settings and triggers a reboot of host system.
+ - This is applied to the host after the restart.
+ - This operation will not create any job.
+ - C(false) does not perform any operation.
+ - This is mutually exclusive with I(boot_sources), I(attributes), and I(clear_pending).
+ - When C(true), this action will always report as changes found to be applicable.
+ reset_type:
+ type: str
+ description:
+ - C(force_restart) Forcefully reboot the host system.
+ - C(graceful_restart) Gracefully reboot the host system.
+ - This is applicable for I(reset_bios), and I(attributes) when I(apply_time) is C(Immediate).
+ choices: [graceful_restart, force_restart]
+ default: graceful_restart
+ job_wait:
+ type: bool
+ description:
+ - Provides the option to wait for job completion.
+ - This is applicable for I(attributes) when I(apply_time) is C(Immediate).
+ default: true
+ job_wait_timeout:
+ type: int
+ description:
+ - The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.
+ - This option is applicable when I(job_wait) is C(true).
+ default: 1200
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/main.yml
new file mode 100644
index 000000000..e660452c3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/meta/main.yml
@@ -0,0 +1,25 @@
+galaxy_info:
+ author: Abhishek Sinha ('Abhishek-Dell')
+ description: The role performs idrac bios operations.
+ company: Dell Technologies
+
+ license: GPL-3.0-only
+
+ min_ansible_version: '2.13'
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/__get_data.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/__get_data.yml
new file mode 100644
index 000000000..a7ee9c67e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/__get_data.yml
@@ -0,0 +1,16 @@
+---
+- name: Get uri data
+ ansible.builtin.uri:
+ url: "{{ url }}"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ body: {}
+ body_format: json
+ force_basic_auth: true
+ return_content: true
+ status_code: 200
+ headers: 'Accept=application/json'
+ check_mode: false
+ no_log: true
+ register: idrac_bios_uri_data
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/converge.yml
new file mode 100644
index 000000000..d81646ccb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge file for clear pending attributes
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Clear pending attributes
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ clear_pending: true
+
+ - name: Verify clear pending attributes in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.clear_pending.status_msg == "Successfully cleared
+ the pending BIOS attributes."
+ - idrac_bios_out.reset_bios.skipped
+ - idrac_bios_out.attributes.skipped
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verify clear pending attributes in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.clear_pending.status_msg == "Changes found
+ to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verify clear pending attributes in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.clear_pending.status_msg == "No changes found
+ to be applied."
+ when: not ansible_check_mode and not idrac_bios_out.clear_pending.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/prepare.yml
new file mode 100644
index 000000000..46d74222a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/clear_pending_attributes/prepare.yml
@@ -0,0 +1,62 @@
+---
+- name: Converge file to update attributes with apply time as Immediate
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_port: "{{ lookup('env', 'IDRAC_PORT') }}"
+ tasks:
+ - name: Fetch Jobs Data
+ ansible.builtin.include_tasks:
+ file: ../__get_data.yml
+ vars:
+ url: "https://{{ idrac_ip }}:{{ idrac_port }}/redfish/v1/Managers\
+ /iDRAC.Embedded.1/Jobs?$expand=*($levels=1)"
+
+ - name: Fetch Bios Jobs Data
+ when: idrac_bios_uri_data.json.Members | length > 0
+ ansible.builtin.set_fact:
+ idrac_bios_jobs_items: "{{ idrac_bios_uri_data.json.Members
+ | json_query(query) }}"
+ vars:
+ query: "[?JobType=='BIOSConfiguration' && JobState=='Scheduled'
+ || JobState=='Scheduling' ]"
+ no_log: true
+
+ - name: Block for creating a bios job as a pre-requisite
+ when: idrac_bios_jobs_items | length == 0
+ block:
+ - name: Fetch IDRAC Data
+ ansible.builtin.include_tasks:
+ file: ../__get_data.yml
+ vars:
+ url: "https://{{ idrac_ip }}:{{ idrac_port }}/redfish/v1/\
+ Systems/System.Embedded.1/Bios"
+
+ - name: Fetch the existing boot mode
+ ansible.builtin.set_fact:
+ boot_mode: "{{ idrac_bios_uri_data.json.Attributes.BootMode }}"
+
+ - name: Set the boot mode
+ ansible.builtin.set_fact:
+ set_boot_mode: "{{ 'Bios' if (boot_mode == 'Uefi') else 'Uefi' }}"
+ when: set_boot_mode is not defined
+
+ - name: Update attributes with apply time as Immediate
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ idrac_ip }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: "OnReset"
+ attributes:
+ BootMode: "{{ set_boot_mode }}"
+ register: idrac_bios_change_bios_setting
+
+ - name: Verify job is scheduled
+ ansible.builtin.assert:
+ that:
+ - "'Successfully committed changes. The job is in pending state'
+ in idrac_bios_out.attributes.status_msg"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/converge.yml
new file mode 100644
index 000000000..6f8488153
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/converge.yml
@@ -0,0 +1,135 @@
+---
+- name: Converge file for negative scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ ########## Below snippet is commented because of Issue: JIT-285533 ########
+ # - name: Perform reset bios with invalid hostname
+ # ansible.builtin.import_role:
+ # name: idrac_bios
+ # vars:
+ # hostname: "randomHostname"
+ # username: "{{ lookup('env', 'IDRAC_USER') }}"
+ # password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ # validate_certs: false
+ # reset_bios: true
+ # ignore_unreachable: true
+
+ # - name: Assert reset bios with invalid hostname
+ # ansible.builtin.assert:
+ # that:
+ # - "'Unable to communicate with iDRAC randomHostname' in
+ # idrac_bios_out.reset_bios.msg"
+ ###########################################################################
+
+ - name: Block to reset bios with invalid username
+ block:
+ - name: Perform reset bios with invalid username
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "randomusername"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_bios: true
+ clear_pending: false
+ rescue:
+ - name: Verify reset bios with invalid username
+ ansible.builtin.assert:
+ that:
+ - "'HTTP Error 401' in ansible_failed_result.msg"
+
+ - name: Block for clear pending attributes with invalid value
+ block:
+ - name: Clear pending attributes with invalid value
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ clear_pending: yess
+ rescue:
+ - name: Assert clear pending attributes with invalid value
+ ansible.builtin.assert:
+ that: ansible_failed_result.msg is
+ search('unable to convert to bool')
+
+ - name: Block for reset bios with invalid value
+ block:
+ - name: Perform reset bios with invalid value
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_bios: truee
+ rescue:
+ - name: Assert perform reset bios with invalid value
+ ansible.builtin.assert:
+ that: ansible_failed_result.msg is
+ search('unable to convert to bool')
+
+ - name: Block for reset bios with invalid password
+ block:
+ - name: Perform reset bios with invalid password
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "randompassword"
+ validate_certs: false
+ clear_pending: false
+ reset_bios: true
+ rescue:
+ - name: Assert reset bios with invalid password
+ ansible.builtin.assert:
+ that: |-
+ ("'HTTP Error 401' in ansible_failed_result.msg")
+ or
+ ("'urlopen error timed out' in ansible_failed_result.msg")
+
+ - name: Block for reset type with invalid value
+ block:
+ - name: Perform reset type with invalid value
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ clear_pending: false
+ reset_bios: true
+ reset_type: graceful_restartt
+ rescue:
+ - name: Assert reset type with invalid value
+ ansible.builtin.assert:
+ that:
+ - ansible_failed_result.msg is
+ search('value of reset_type must be one of')
+ - ansible_failed_result.msg is
+ search('graceful_restart, force_restart')
+
+ - name: Clear pending attributes with reset
+ block:
+ - name: Clear pending attributes with reset
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ clear_pending: true
+ reset_bios: true
+ rescue:
+ - name: Assert clear pending attributes with reset
+ ansible.builtin.assert:
+ that: "ansible_failed_result.msg is
+ search('clear_pending and reset_bios is mutually exclusive')"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/molecule.yml
new file mode 100644
index 000000000..210914970
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/default/molecule.yml
@@ -0,0 +1,6 @@
+---
+scenario:
+ test_sequence:
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/converge.yml
new file mode 100644
index 000000000..44439ab07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/converge.yml
@@ -0,0 +1,159 @@
+---
+- name: Converge file for negative scenarios with maintenance window
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Block to update attributes with maintenance window and no start_time
+ block:
+ - name: Update attributes with maintenance window and no start_time
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ duration: 600
+ attributes:
+ BootMode: "Bios"
+ rescue:
+ - name: Assert update attributes with maintenance window
+ and no start_time
+ ansible.builtin.assert:
+ that: "ansible_failed_result.msg is
+ search('missing required arguments')"
+
+ - name: Block to update attributes with maintenance window
+ with invalid start_time
+ block:
+ - name: Update attributes with maintenance window with
+ invalid start_time
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ start_time: "2022"
+ duration: 600
+ attributes:
+ BootMode: "Bios"
+ rescue:
+ - name: Assert update attributes with maintenance window
+ with invalid start_time
+ ansible.builtin.assert:
+ that: "idrac_bios_out.attributes.status_msg is search('The
+ maintenance time must be post-fixed with local offset
+ to -06:00.')"
+
+ - name: Block to update attributes with maintenance window
+ with invalid duration
+ block:
+ - name: Update attributes with maintenance window with invalid duration
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ start_time: "2022-30-09T05:15:40-21"
+ duration: "10 minutes"
+ attributes:
+ BootMode: "Bios"
+ rescue:
+ - name: Assert update attributes with maintenance window
+ with invalid duration
+ ansible.builtin.assert:
+ that:
+ - "ansible_failed_result.msg is
+ search('Validation of arguments failed')"
+
+ - name: Block to update attributes with maintenance window
+ with invalid apply time
+ block:
+ - name: Update attributes with maintenance window
+ with invalid apply time
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: AtMaintenanceWindowBegin
+ maintenance_window:
+ start_time: "2022-30-09T05:15:40-21"
+ duration: 10
+ attributes:
+ BootMode: "Bios"
+ rescue:
+ - name: Assert update attributes with maintenance window
+ with invalid apply time
+ ansible.builtin.assert:
+ that:
+ - "ansible_failed_result.msg is search('value of
+ apply_time must be one of')"
+ - "ansible_failed_result.msg is search('Immediate,
+ OnReset, AtMaintenanceWindowStart, InMaintenanceWindowOnReset')"
+
+ - name: Block to update attributes with maintenance
+ window with invalid job wait
+ block:
+ - name: Update attributes with maintenance window with invalid job wait
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ start_time: "2023-05-18T05:17:40-05:00"
+ duration: 600
+ attributes:
+ BootMode: "Bios"
+ job_wait: truee
+ rescue:
+ - name: Assert update attributes with maintenance
+ window with invalid job wait
+ ansible.builtin.assert:
+ that: "ansible_failed_result.msg is
+ search('unable to convert to bool')"
+
+ - name: Block to update attributes with maintenance window
+ with invalid job wait timeout
+ block:
+ - name: Update attributes with maintenance window
+ with invalid job wait timeout
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ start_time: "2023-05-18T05:17:40-05:00"
+ duration: 600
+ attributes:
+ BootMode: "Bios"
+ OneTimeBootMode: "Enabled"
+ BootSeqRetry: "Enabled"
+ job_wait_timeout: -10
+ rescue:
+ - name: Assert attributes with maintenance window
+ with invalid job wait timeout
+ ansible.builtin.assert:
+ that:
+ - "'The parameter job_wait_timeout value cannot
+ be negative or zero' in idrac_bios_out.attributes.msg"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/molecule.yml
new file mode 100644
index 000000000..210914970
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/negative_scenarios_with_maintenance_window/molecule.yml
@@ -0,0 +1,6 @@
+---
+scenario:
+ test_sequence:
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/converge.yml
new file mode 100644
index 000000000..6c2e8098f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/converge.yml
@@ -0,0 +1,32 @@
+---
+- name: Converge file for reset bios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Perform reset bios operation
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_bios: true
+
+ - name: Verify reset bios operation in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.reset_bios.status_msg == "BIOS reset to defaults has
+ been completed successfully."
+ - idrac_bios_out.clear_pending.skipped
+ - idrac_bios_out.attributes.skipped
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verify reset bios operation in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.reset_bios.status_msg == "Changes found
+ to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/molecule.yml
new file mode 100644
index 000000000..608be28b1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios/molecule.yml
@@ -0,0 +1,7 @@
+---
+scenario:
+ test_sequence:
+ - create
+ - check
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/converge.yml
new file mode 100644
index 000000000..03b93a73f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/converge.yml
@@ -0,0 +1,35 @@
+---
+- name: Converge file for reset type as force restart
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Perform reset operation with reset type as force restart
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_bios: true
+ reset_type: force_restart
+
+ - name: Verify reset bios operation with reset type as force
+ restart in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.reset_bios.status_msg == "BIOS reset to defaults
+ has been completed successfully."
+ - idrac_bios_out.clear_pending.skipped
+ - idrac_bios_out.attributes.skipped
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verify reset bios operation with reset type as force restart
+ in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.reset_bios.status_msg == "Changes found to
+ be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/molecule.yml
new file mode 100644
index 000000000..608be28b1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/reset_bios_with_reset_type_as_force_restart/molecule.yml
@@ -0,0 +1,7 @@
+---
+scenario:
+ test_sequence:
+ - create
+ - check
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/cleanup.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/cleanup.yml
new file mode 100644
index 000000000..a107545a8
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/cleanup.yml
@@ -0,0 +1,17 @@
+---
+- name: CleanUp file for update attributes with apply time as Immediate
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Checking file exists- boot_mode.txt
+ ansible.builtin.stat:
+ path: "/tmp/boot_mode.txt"
+ delegate_to: localhost
+ register: boot_mode_file
+
+ - name: Deleting the file if exists
+ ansible.builtin.file:
+ path: "/tmp/boot_mode.txt"
+ state: absent
+ delegate_to: localhost
+ when: boot_mode_file.stat.exists
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/prepare.yml
new file mode 100644
index 000000000..a8bf8042b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/resources/prepare.yml
@@ -0,0 +1,30 @@
+---
+- name: Prepare file to update attributes with apply time as Immediate
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_port: "{{ lookup('env', 'IDRAC_PORT') }}"
+ tasks:
+ - name: Fetch IDRAC Data
+ ansible.builtin.include_tasks:
+ file: ../__get_data.yml
+ vars:
+ url: "https://{{ idrac_ip }}:{{ idrac_port }}/redfish/v1/\
+ Systems/System.Embedded.1/Bios"
+
+ - name: Fetch the existing boot mode
+ ansible.builtin.set_fact:
+ boot_mode: "{{ idrac_bios_uri_data.json.Attributes.BootMode }}"
+
+ - name: Set the boot mode
+ ansible.builtin.set_fact:
+ set_boot_mode: "{{ 'Bios' if (boot_mode == 'Uefi') else 'Uefi' }}"
+ when: set_boot_mode is not defined
+
+ - name: Copy the variable 'set_boot_mode' in file
+ ansible.builtin.copy:
+ content: "{{ set_boot_mode }}"
+ dest: "/tmp/boot_mode.txt"
+ mode: "0755"
+ delegate_to: localhost
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/converge.yml
new file mode 100644
index 000000000..9c247b7a1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/converge.yml
@@ -0,0 +1,54 @@
+---
+- name: Converge file to update attributes with apply time as Immediate
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Read file content for set_boot_mode variable
+ ansible.builtin.command: cat /tmp/boot_mode.txt
+ register: file_content
+ check_mode: false
+ delegate_to: localhost
+ changed_when: true
+
+ - name: Set set_boot_mode variable
+ ansible.builtin.set_fact:
+ set_boot_mode: "{{ file_content.stdout }}"
+ delegate_to: localhost
+
+ - name: Update attributes with apply time as Immediate
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: Immediate
+ attributes:
+ BootMode: "{{ set_boot_mode }}"
+
+ - name: Assert update attributes with apply time as Immediate - normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Successfully applied the
+ BIOS attributes update."
+ - idrac_bios_out.reset_bios.skipped
+ - idrac_bios_out.clear_pending.skipped
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Assert update attributes with apply time as Immediate - check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Changes found to
+ be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Assert update attributes with apply time as Immediate
+ in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "No changes found
+ to be applied."
+ when: not ansible_check_mode and not idrac_bios_out.attributes.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/molecule.yml
new file mode 100644
index 000000000..df2ebca6b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate/molecule.yml
@@ -0,0 +1,6 @@
+---
+provisioner:
+ name: ansible
+ playbooks:
+ prepare: ../resources/prepare.yml
+ cleanup: ../resources/cleanup.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/converge.yml
new file mode 100644
index 000000000..1800ce04f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/converge.yml
@@ -0,0 +1,60 @@
+---
+- name: Converge file to update attributes with
+ apply time as Immediate with job wait
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_port: "{{ lookup('env', 'IDRAC_PORT') }}"
+ tasks:
+ - name: Read file content for set_boot_mode variable
+ ansible.builtin.command: cat /tmp/boot_mode.txt
+ register: file_content
+ check_mode: false
+ delegate_to: localhost
+ changed_when: true
+
+ - name: Set set_boot_mode variable
+ ansible.builtin.set_fact:
+ set_boot_mode: "{{ file_content.stdout }}"
+ delegate_to: localhost
+
+ - name: Update attributes with apply time as Immediate with job wait
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: Immediate
+ attributes:
+ BootMode: "{{ set_boot_mode }}"
+ job_wait: true
+
+ - name: Assert update attributes with apply time as Immediate - normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Successfully
+ applied the BIOS attributes update."
+ - idrac_bios_out.reset_bios.skipped
+ - idrac_bios_out.clear_pending.skipped
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Assert update attributes with apply time as Immediate
+ in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Changes found
+ to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Assert update attributes with apply time as Immediate in
+ idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "No changes found
+ to be applied."
+ when: not ansible_check_mode and not idrac_bios_out.attributes.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/molecule.yml
new file mode 100644
index 000000000..df2ebca6b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_immediate_with_jobwait/molecule.yml
@@ -0,0 +1,6 @@
+---
+provisioner:
+ name: ansible
+ playbooks:
+ prepare: ../resources/prepare.yml
+ cleanup: ../resources/cleanup.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/converge.yml
new file mode 100644
index 000000000..fb36db3b7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/converge.yml
@@ -0,0 +1,50 @@
+---
+- name: Converge file for update attributes with apply time as reset
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_port: "{{ lookup('env', 'IDRAC_PORT') }}"
+ tasks:
+ - name: Read file content for set_boot_mode variable
+ ansible.builtin.command: cat /tmp/boot_mode.txt
+ register: file_content
+ check_mode: false
+ delegate_to: localhost
+ changed_when: true
+
+ - name: Set set_boot_mode variable
+ ansible.builtin.set_fact:
+ set_boot_mode: "{{ file_content.stdout }}"
+ delegate_to: localhost
+
+ - name: Update attributes with apply time as reset
+ ansible.builtin.include_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: OnReset
+ attributes:
+ BootMode: "{{ set_boot_mode }}"
+ job_wait: false
+
+ - name: Assert update attributes with apply time as reset in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Successfully committed
+ changes. The job is in pending state. The changes will be
+ applied OnReset"
+ - idrac_bios_out.reset_bios.skipped
+ - idrac_bios_out.clear_pending.skipped
+
+ when: not ansible_check_mode
+
+ - name: Assert update attributes with apply time as reset in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Changes found
+ to be applied."
+ when: ansible_check_mode
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/molecule.yml
new file mode 100644
index 000000000..d3bacf777
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset/molecule.yml
@@ -0,0 +1,14 @@
+---
+provisioner:
+ name: ansible
+ playbooks:
+ prepare: ../resources/prepare.yml
+ cleanup: ../resources/cleanup.yml
+scenario:
+ test_sequence:
+ - create
+ - prepare
+ - check
+ - converge
+ - cleanup
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/converge.yml
new file mode 100644
index 000000000..7ac8c1bad
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/converge.yml
@@ -0,0 +1,74 @@
+---
+- name: Converge file for update attributes with apply
+ time at reset of maintenance window
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_port: "{{ lookup('env', 'IDRAC_PORT') }}"
+ tasks:
+ - name: Read file content for set_boot_mode variable
+ ansible.builtin.command: cat /tmp/boot_mode.txt
+ register: file_content
+ check_mode: false
+ delegate_to: localhost
+ changed_when: true
+
+ - name: Set set_boot_mode variable
+ ansible.builtin.set_fact:
+ set_boot_mode: "{{ file_content.stdout }}"
+ delegate_to: localhost
+
+ - name: Get tomorrow's date
+ ansible.builtin.command: date -d "+1 day" +'%Y-%m-%dT%H:%M:%S'
+ register: tomorrow_date
+ changed_when: false
+
+ - name: Convert tomorrow's date to string
+ ansible.builtin.set_fact:
+ date_str: "{{ tomorrow_date.stdout }}"
+
+ - name: Fetch IDRAC time offset
+ ansible.builtin.include_tasks:
+ file: ../__get_data.yml
+ vars:
+ url: "https://{{ idrac_ip }}:{{ idrac_port }}/redfish/v1\
+ /Managers/iDRAC.Embedded.1"
+
+ - name: Set the local offset
+ when: idrac_bios_uri_data.json.DateTimeLocalOffset is defined
+ ansible.builtin.set_fact:
+ local_offset: "{{ idrac_bios_uri_data.json.DateTimeLocalOffset }}"
+
+ - name: Update attributes with apply time at reset of maintenance window
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: InMaintenanceWindowOnReset
+ maintenance_window:
+ start_time: "{{ date_str }}{{ local_offset }}"
+ duration: 600
+ attributes:
+ BootMode: "{{ set_boot_mode }}"
+
+ - name: Assert update attributes with apply time at reset
+ of maintenance window normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Successfully committed changes. The job is in pending state'
+ in idrac_bios_out.attributes.status_msg"
+ - idrac_bios_out.reset_bios.skipped
+ - idrac_bios_out.clear_pending.skipped
+ when: not ansible_check_mode
+
+ - name: Assert Update attributes with apply time at reset of
+ maintenance window in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Changes found to
+ be applied."
+ when: ansible_check_mode
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/molecule.yml
new file mode 100644
index 000000000..d3bacf777
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_on_reset_with_maintenance_window/molecule.yml
@@ -0,0 +1,14 @@
+---
+provisioner:
+ name: ansible
+ playbooks:
+ prepare: ../resources/prepare.yml
+ cleanup: ../resources/cleanup.yml
+scenario:
+ test_sequence:
+ - create
+ - prepare
+ - check
+ - converge
+ - cleanup
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/converge.yml
new file mode 100644
index 000000000..43004cea7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/converge.yml
@@ -0,0 +1,74 @@
+---
+- name: Converge file to update attributes with apply time
+ at start of maintenance window
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_port: "{{ lookup('env', 'IDRAC_PORT') }}"
+ tasks:
+ - name: Read file content for set_boot_mode variable
+ ansible.builtin.command: cat /tmp/boot_mode.txt
+ register: file_content
+ check_mode: false
+ delegate_to: localhost
+ changed_when: true
+
+ - name: Set set_boot_mode variable
+ ansible.builtin.set_fact:
+ set_boot_mode: "{{ file_content.stdout }}"
+ delegate_to: localhost
+
+ - name: Get tomorrow's date
+ ansible.builtin.command: date -d "+1 day" +'%Y-%m-%dT%H:%M:%S'
+ register: tomorrow_date
+ changed_when: false
+
+ - name: Convert tomorrow's date to string
+ ansible.builtin.set_fact:
+ date_str: "{{ tomorrow_date.stdout }}"
+
+ - name: Fetch IDRAC time offset
+ ansible.builtin.include_tasks:
+ file: ../__get_data.yml
+ vars:
+ url: "https://{{ idrac_ip }}:{{ idrac_port }}/redfish/v1\
+ /Managers/iDRAC.Embedded.1"
+
+ - name: Set the local offset
+ when: idrac_bios_uri_data.json.DateTimeLocalOffset is defined
+ ansible.builtin.set_fact:
+ local_offset: "{{ idrac_bios_uri_data.json.DateTimeLocalOffset }}"
+
+ - name: Update attributes with apply time at start of maintenance window
+ ansible.builtin.import_role:
+ name: idrac_bios
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ start_time: "{{ date_str }}{{ local_offset }}"
+ duration: 600
+ attributes:
+ BootMode: "{{ set_boot_mode }}"
+
+ - name: Assert update attributes with apply time at start of
+ maintenance window in normal mode
+ ansible.builtin.assert:
+ that:
+ - "'Successfully committed changes. The job is in pending state' in
+ idrac_bios_out.attributes.status_msg"
+ - idrac_bios_out.reset_bios.skipped
+ - idrac_bios_out.clear_pending.skipped
+ when: not ansible_check_mode
+
+ - name: Assert update attributes with apply time at start of
+ maintenance window in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_bios_out.attributes.status_msg == "Changes found to
+ be applied."
+ when: ansible_check_mode
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/molecule.yml
new file mode 100644
index 000000000..d3bacf777
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/molecule/update_attributes_with_maintenance_window/molecule.yml
@@ -0,0 +1,14 @@
+---
+provisioner:
+ name: ansible
+ playbooks:
+ prepare: ../resources/prepare.yml
+ cleanup: ../resources/cleanup.yml
+scenario:
+ test_sequence:
+ - create
+ - prepare
+ - check
+ - converge
+ - cleanup
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/tasks/main.yml
new file mode 100644
index 000000000..18567035c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/tasks/main.yml
@@ -0,0 +1,67 @@
+---
+# tasks file for idrac_bios
+- name: Performing idrac_bios operation
+ block:
+ - name: Checking attributes/clear_pending and reset_bios is mutually exclusive
+ ansible.builtin.fail:
+ msg: "{{ idrac_bios_mutual_exclusive_msg }}"
+ when:
+ - (attributes is defined and (reset_bios is defined and reset_bios))
+ or
+ (clear_pending and (reset_bios is defined and reset_bios))
+
+ - name: Setting idrac_inputs
+ ansible.builtin.set_fact:
+ idrac_inputs: &idrac_inputs
+ idrac_ip: "{{ hostname }}"
+ idrac_port: "{{ https_port }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ https_timeout }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ no_log: true
+
+ - name: Performing clear pending operation
+ dellemc.openmanage.idrac_bios:
+ <<: *idrac_inputs
+ clear_pending: "{{ clear_pending }}"
+ register: idrac_bios_clear_pending_out
+ delegate_to: "{{ idrac_bios_delegate }}"
+ when: clear_pending
+
+ - name: Configuring the bios attributes
+ dellemc.openmanage.idrac_bios:
+ <<: *idrac_inputs
+ attributes: "{{ attributes }}"
+ apply_time: "{{ apply_time }}"
+ maintenance_window: "{{ maintenance_window | default(omit) }}"
+ reset_type: "{{ reset_type }}"
+ register: idrac_bios_attributes_out
+ delegate_to: "{{ idrac_bios_delegate }}"
+ when: attributes is defined
+
+ - name: Performing the reset bios operation
+ dellemc.openmanage.idrac_bios:
+ <<: *idrac_inputs
+ reset_bios: "{{ reset_bios }}"
+ reset_type: "{{ reset_type }}"
+ register: idrac_bios_reset_bios_out
+ delegate_to: "{{ idrac_bios_delegate }}"
+ when: reset_bios is defined and reset_bios
+
+ always:
+ - name: Set fact for idrac_bios_out
+ ansible.builtin.set_fact:
+ idrac_bios_out: "{{ idrac_bios_out | default({}) | combine({item.key: item.value}) }}"
+ with_items:
+ - { "key": "clear_pending", "value": "{{ idrac_bios_clear_pending_out }}" }
+ - { "key": "attributes", "value": "{{ idrac_bios_attributes_out }}" }
+ - { "key": "reset_bios", "value": "{{ idrac_bios_reset_bios_out }}" }
+ no_log: true
+
+ - name: Printing idrac_bios_out
+ ansible.builtin.debug:
+ var: idrac_bios_out
diff --git a/ansible_collections/dellemc/os6/roles/os6_qos/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_bios/tests/inventory
index 878877b07..878877b07 100644
--- a/ansible_collections/dellemc/os6/roles/os6_qos/tests/inventory
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/tests/inventory
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/tests/test.yml
new file mode 100644
index 000000000..ec7d7f005
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Testing idrac_bios
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_bios
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_bios/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_bios/vars/main.yml
new file mode 100644
index 000000000..cdba5a342
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_bios/vars/main.yml
@@ -0,0 +1,7 @@
+---
+# vars file for idrac_bios
+idrac_bios_mutual_exclusive_msg: "attributes/clear_pending and reset_bios is mutually exclusive."
+idrac_bios_clear_pending_out: ""
+idrac_bios_attributes_out: ""
+idrac_bios_reset_bios_out: ""
+idrac_bios_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_boot/README.md
new file mode 100644
index 000000000..f7903b07e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/README.md
@@ -0,0 +1,373 @@
+# idrac_boot
+
+Role to configure the boot order settings
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role
+```
+ansible
+docker
+molecule
+python
+```
+
+### Production
+Requirements to use the role
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>boot_options</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>list</td>
+ <td>- Options to enable or disable the boot devices.<br>- This is mutually exclusive with I(boot_order), I(boot_source_override_mode), I(boot_source_override_enabled), I(boot_source_override_target), and I(uefi_target_boot_source_override).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boot_option_reference</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- FQDD of the boot device.<br>- This is mutually exclusive with I(display_name).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Display name of the boot source device.<br>- This is mutually exclusive with I(boot_option_reference).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enabled</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Enable or disable the boot device.</td>
+ </tr>
+ <tr>
+ <td>boot_order</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>list</td>
+ <td>- This option allows to set the boot devices in the required boot order sequence.<br>- This is mutually exclusive with I(boot_options).</td>
+ </tr>
+ <tr>
+ <td>boot_source_override_mode</td>
+ <td>false</td>
+ <td></td>
+ <td>'legacy', 'uefi'</td>
+ <td>str</td>
+ <td>- The BIOS boot mode (either Legacy or UEFI) to be used when I(boot_source_override_target) boot source is booted.<br>- C(legacy) The system boot in non-UEFI(Legacy) boot mode to the I(boot_source_override_target).<br>- C(uefi) The system boot in UEFI boot mode to the I(boot_source_override_target).<br>- This is mutually exclusive with I(boot_options).</td>
+ </tr>
+ <tr>
+ <td>boot_source_override_enabled</td>
+ <td>false</td>
+ <td></td>
+ <td>'continuous', 'disabled', 'once'</td>
+ <td>str</td>
+ <td>- The state of the Boot Source Override feature.<br>- C(disabled), the system boots normally.<br>- C(once), the system boots 1 time to the I(boot_source_override_target).<br>- C(continuous), the system boots to the target specified in the I(boot_source_override_target) until this property is set to Disabled.<br>- The state is set to C(once) for the 1 time boot override and C(continuous) for the remain-active-until—cancelled override. If the state is set C(once) or C(continuous), the value is reset to C(disabled) after the I(boot_source_override_target) actions have completed successfully.<br>- Changes to these options do not alter the BIOS persistent boot order configuration.<br>- This is mutually exclusive with I(boot_options).</td>
+ </tr>
+ <tr>
+ <td>boot_source_override_target</td>
+ <td>false</td>
+ <td></td>
+ <td>'uefi_http', 'sd_card', 'uefi_target', 'utilities', 'bios_setup', 'hdd', 'cd', 'floppy', 'pxe', 'none'</td>
+ <td>str</td>
+ <td>- The boot source override targets the device to use during the next boot instead of the normal boot device.<br>- C(pxe) performs PXE boot from the primary NIC.<br>- C(floppy), C(cd), C(hdd), and C(sd_card) performs boot from their devices respectively.<br>- C(bios_setup) performs boot into the native BIOS setup.<br>- C(uefi_http) performs boot from a URI over HTTP.<br>- C(utilities) performs boot from the local utilities.<br>- C(uefi_target) performs boot from the UEFI device path found in I(uefi_target_boot_source_override).<br>- C(none) if the I(boot_source_override_target) is set to a value other than C(none) then the I(boot_source_override_enabled) is automatically set to C(once).<br>- Changes to these options do not alter the BIOS persistent boot order configuration.<br>- This is mutually exclusive with I(boot_options).</td>
+ </tr>
+ <tr>
+ <td>uefi_target_boot_source_override</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The UEFI device path of the device from which to boot when I(boot_source_override_target) is C(uefi_target).<br>- If I(boot_source_override_target) is set to C(uefi_target), then I(boot_source_override_enabled) cannot be set to c(continuous) because this setting is defined in UEFI as a one-time-boot setting.<br>- Changes to these options do not alter the BIOS persistent boot order configuration.<br>- This is required if I(boot_source_override_target) is C(uefi_target).<br>- This is mutually exclusive with I(boot_options).</td>
+ </tr>
+ <tr>
+ <td>reset_type</td>
+ <td>false</td>
+ <td>graceful_restart</td>
+ <td>'graceful_restart', 'force_restart', 'none'</td>
+ <td>str</td>
+ <td>- C(none) Host system is not rebooted and I(job_wait) is not applicable.<br>- C(force_restart) Forcefully reboot the Host system.<br>- C(graceful_restart) Gracefully reboot the Host system.</td>
+ </tr>
+ <tr>
+ <td>job_wait</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Provides the option to wait for job completion.<br>- This is applicable when I(reset_type) is C(force_reset) or C(graceful_reset).</td>
+ </tr>
+ <tr>
+ <td>job_wait_timeout</td>
+ <td>false</td>
+ <td>900</td>
+ <td></td>
+ <td>int</td>
+ <td>- The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.<br>- This option is applicable when I(job_wait) is C(True).</td>
+ </tr>
+ <tr>
+ <td>resource_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Redfish ID of the resource.</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_boot_out</td>
+ <td>{
+ "boot": {
+ "BootOptions": {
+ "Description": "Collection of BootOptions",
+ "Members": [
+ {
+ "BootOptionEnabled": true,
+ "BootOptionReference": "Boot0005",
+ "Description": "Current settings of the UEFI Boot option",
+ "DisplayName": "Integrated RAID Controller 1: VMware ESXi",
+ "Id": "Boot0005",
+ "Name": "Uefi Boot Option",
+ "UefiDevicePath": "HD(1,GPT,740C46A9-4A43-47AA-9C09-65E821376E48,0x40,0x32000)/\\EFI\\VMware\\safeboot64.efi"
+ },
+ {
+ "BootOptionEnabled": false,
+ "BootOptionReference": "Boot0004",
+ "Description": "Current settings of the UEFI Boot option",
+ "DisplayName": "Unavailable: Windows Boot Manager",
+ "Id": "Boot0004",
+ "Name": "Uefi Boot Option",
+ "UefiDevicePath": "HD(1,GPT,AEB2A96B-5C31-4F8F-9927-B48B08D907BE,0x800,0xF9800)/\\EFI\\Microsoft\\Boot\\bootmgfw.efi"
+ },
+ {
+ "BootOptionEnabled": true,
+ "BootOptionReference": "Boot0006",
+ "Description": "Current settings of the UEFI Boot option",
+ "DisplayName": "Unavailable: Red Hat Enterprise Linux",
+ "Id": "Boot0006",
+ "Name": "Uefi Boot Option",
+ "UefiDevicePath": "HD(1,GPT,14759088-1AE7-4EA4-A60B-BE82546E21B6,0x800,0x12C000)/\\EFI\\redhat\\shimx64.efi"
+ },
+ {
+ "BootOptionEnabled": true,
+ "BootOptionReference": "Boot0003",
+ "Description": "Current settings of the UEFI Boot option",
+ "DisplayName": "Unavailable: Rocky Linux",
+ "Id": "Boot0003",
+ "Name": "Uefi Boot Option",
+ "UefiDevicePath": "HD(1,GPT,ADC59C44-A0D3-4917-9376-33EE44DE96F0,0x800,0x12C000)/\\EFI\\rocky\\shimx64.efi"
+ }
+ ],
+ "Name": "Boot Options Collection"
+ },
+ "BootOrder": [
+ "Boot0005",
+ "Boot0004",
+ "Boot0006",
+ "Boot0003"
+ ],
+ "BootSourceOverrideEnabled": "Disabled",
+ "BootSourceOverrideMode": "UEFI",
+ "BootSourceOverrideTarget": "None",
+ "UefiTargetBootSourceOverride": null
+ },
+ "job": {
+ "ActualRunningStartTime": "2023-06-19T09:48:41",
+ "ActualRunningStopTime": "2023-06-19T09:51:53",
+ "CompletionTime": "2023-06-19T09:51:53",
+ "Description": "Job Instance",
+ "EndTime": "TIME_NA",
+ "Id": "JID_871679370016",
+ "JobState": "Completed",
+ "JobType": "BIOSConfiguration",
+ "Message": "Job completed successfully.",
+ "MessageArgs": [],
+ "MessageId": "PR19",
+ "Name": "Configure: BIOS.Setup.1-1",
+ "PercentComplete": 100,
+ "StartTime": "2023-06-19T09:45:36",
+ "TargetSettingsURI": null
+ },
+ "msg": "Successfully updated the boot settings."
+}</td>
+ <td>Role output of the idrac_boot job.</td>
+ </tr>
+ </tbody>
+</table>
+
+## Example Playbook
+
+```
+- name: Configure the system boot options settings.
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_boot
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ boot_options:
+ - display_name: Hard drive C
+ enabled: true
+ - boot_option_reference: NIC.PxeDevice.2-1
+ enabled: true
+```
+
+```
+- name: Configure the boot order settings.
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_boot
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ boot_order:
+ - Boot0001
+ - Boot0002
+ - Boot0004
+ - Boot0003
+```
+
+```
+- name: Configure the boot source override mode.
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_boot
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ boot_source_override_mode: legacy
+ boot_source_override_target: cd
+ boot_source_override_enabled: once
+```
+
+```
+- name: Configure the UEFI target settings.
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_boot
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ boot_source_override_mode: uefi
+ boot_source_override_target: uefi_target
+ uefi_target_boot_source_override: "VenHw(3A191845-5F86-4E78-8FCE-C4CFF59F9DAA)"
+```
+
+```
+- name: Configure the boot source override mode as pxe.
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_boot
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ boot_source_override_mode: legacy
+ boot_source_override_target: pxe
+ boot_source_override_enabled: continuous
+```
+
+Author Information
+------------------
+
+Dell Technologies <br>
+Felix Stephen (felix_s@dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/defaults/main.yml
new file mode 100644
index 000000000..8a8919ff5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+reset_type: graceful_restart
+job_wait: true
+job_wait_timeout: 900
+https_port: 443
+https_timeout: 30
+validate_certs: true
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/handlers/main.yml
new file mode 100644
index 000000000..143bdf802
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_boot
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/argument_specs.yml
new file mode 100644
index 000000000..d90140e06
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/argument_specs.yml
@@ -0,0 +1,133 @@
+---
+argument_specs:
+ main:
+ version_added: "8.0.0"
+ short_description: Configure the boot order settings
+ description:
+ - This role allows to configure the boot order settings.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ username:
+ type: str
+ description: iDRAC username.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ boot_options:
+ description:
+ - Options to enable or disable the boot devices.
+ - This is mutually exclusive with I(boot_order), I(boot_source_override_mode),
+ I(boot_source_override_enabled), I(boot_source_override_target), and I(uefi_target_boot_source_override).
+ type: list
+ elements: dict
+ options:
+ boot_option_reference:
+ description:
+ - FQDD of the boot device.
+ - This is mutually exclusive with I(display_name).
+ type: str
+ display_name:
+ description:
+ - Display name of the boot source device.
+ - This is mutually exclusive with I(boot_option_reference).
+ type: str
+ enabled:
+ description: Enable or disable the boot device.
+ type: bool
+ required: true
+ boot_order:
+ description:
+ - This option allows to set the boot devices in the required boot order sequence.
+ - This is mutually exclusive with I(boot_options).
+ type: list
+ elements: str
+ boot_source_override_mode:
+ description:
+ - The BIOS boot mode (either Legacy or UEFI) to be used when I(boot_source_override_target)
+ boot source is booted.
+ - C(legacy) The system boot in non-UEFI(Legacy) boot mode to the I(boot_source_override_target).
+ - C(uefi) The system boot in UEFI boot mode to the I(boot_source_override_target).
+ - This is mutually exclusive with I(boot_options).
+ type: str
+ choices: [legacy, uefi]
+ boot_source_override_enabled:
+ description:
+ - The state of the Boot Source Override feature.
+ - C(disabled), the system boots normally.
+ - C(once), the system boots 1 time to the I(boot_source_override_target).
+ - C(continuous), the system boots to the target specified in the I(boot_source_override_target)
+ until this property is set to Disabled.
+ - The state is set to C(once) for the 1 time boot override and C(continuous) for the
+ remain-active-until—cancelled override. If the state is set C(once) or C(continuous), the value is reset
+ to C(disabled) after the I(boot_source_override_target) actions have completed successfully.
+ - Changes to these options do not alter the BIOS persistent boot order configuration.
+ - This is mutually exclusive with I(boot_options).
+ choices: [continuous, disabled, once]
+ boot_source_override_target:
+ description:
+ - The boot source override targets the device to use during the next boot instead of the normal boot device.
+ - C(pxe) performs PXE boot from the primary NIC.
+ - C(floppy), C(cd), C(hdd), and C(sd_card) performs boot from their devices respectively.
+ - C(bios_setup) performs boot into the native BIOS setup.
+ - C(uefi_http) performs boot from a URI over HTTP.
+ - C(utilities) performs boot from the local utilities.
+ - C(uefi_target) performs boot from the UEFI device path found in I(uefi_target_boot_source_override).
+ - C(none) if the I(boot_source_override_target) is set to a value other than C(none) then the
+ I(boot_source_override_enabled) is automatically set to C(once).
+ - Changes to these options do not alter the BIOS persistent boot order configuration.
+ - This is mutually exclusive with I(boot_options).
+ type: str
+ choices: [uefi_http, sd_card, uefi_target, utilities, bios_setup, hdd, cd, floppy, pxe, none]
+ uefi_target_boot_source_override:
+ description:
+ - The UEFI device path of the device from which to boot when I(boot_source_override_target) is C(uefi_target).
+ - If I(boot_source_override_target) is set to C(uefi_target), then I(boot_source_override_enabled) cannot be
+ set to c(continuous) because this setting is defined in UEFI as a one-time-boot setting.
+ - Changes to these options do not alter the BIOS persistent boot order configuration.
+ - This is required if I(boot_source_override_target) is C(uefi_target).
+ - This is mutually exclusive with I(boot_options).
+ type: str
+ reset_type:
+ description:
+ - C(none) Host system is not rebooted and I(job_wait) is not applicable.
+ - C(force_restart) Forcefully reboot the Host system.
+ - C(graceful_restart) Gracefully reboot the Host system.
+ type: str
+ choices: [graceful_restart, force_restart, none]
+ default: graceful_restart
+ job_wait:
+ description:
+ - Provides the option to wait for job completion.
+ - This is applicable when I(reset_type) is C(force_reset) or C(graceful_reset).
+ type: bool
+ default: true
+ job_wait_timeout:
+ description:
+ - The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.
+ - This option is applicable when I(job_wait) is C(True).
+ type: int
+ default: 900
+ resource_id:
+ description: Redfish ID of the resource.
+ type: str
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/main.yml
new file mode 100644
index 000000000..116f8e05a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/meta/main.yml
@@ -0,0 +1,26 @@
+galaxy_info:
+ role_name: idrac_boot
+ author: "Felix Stephen"
+ description: Role to configure the boot order settings
+ company: Dell Technologies
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.13"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/converge.yml
new file mode 100644
index 000000000..7db461ce1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/converge.yml
@@ -0,0 +1,119 @@
+---
+- name: Testing boot_options_using_boot_option_reference_enabled_true
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_option_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1/BootOptions?$expand=*($levels=1)"
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Fetching boot_option_reference from iDRAC
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ boot_option_uri }}"
+ method: GET
+ register: result_data
+ check_mode: false
+ no_log: true
+
+ - name: Extracing BootOptionReference from output
+ ansible.builtin.set_fact:
+ data: "{{ result_data.json.Members[0].BootOptionReference }}"
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure enabled is false on first boot_option_reference
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_options:
+ - boot_option_reference: "{{ data | default('') }}"
+ enabled: false
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115424 - Validate boot_options using boot_option_reference and default enabled
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_options:
+ - boot_option_reference: "{{ data | default('') }}"
+ enabled: true
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115424 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115424 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Successfully updated the boot settings."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115424 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_boot_option_reference_enabled_true/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/converge.yml
new file mode 100644
index 000000000..9bf8ed1e4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/converge.yml
@@ -0,0 +1,119 @@
+---
+- name: Testing boot_options_using_display_name_enabled_false
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_option_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1/BootOptions?$expand=*($levels=1)"
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Fetching iDRAC
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ boot_option_uri }}"
+ method: GET
+ register: result_data
+ check_mode: false
+ no_log: true
+
+ - name: Extracing DisplayName from output
+ ansible.builtin.set_fact:
+ data: "{{ result_data.json.Members[0].DisplayName }}"
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure enabled is true for fisrt display_name
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_options:
+ - display_name: "{{ data | default('') }}"
+ enabled: true
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115426 - Validate boot_options using display_name and enabled false
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_options:
+ - display_name: "{{ data | default('') }}"
+ enabled: false
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115426 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115426 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Successfully updated the boot settings."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115426 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_options_using_display_name_enabled_false/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/converge.yml
new file mode 100644
index 000000000..92d1958d7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/converge.yml
@@ -0,0 +1,120 @@
+---
+- name: Testing boot_order_using_legacy_mode_force_restart
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_order_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1/"
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Fetching boot order from iDRAC
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ boot_order_uri }}"
+ method: GET
+ register: result_data
+ check_mode: false
+ no_log: true
+
+ - name: Extracing BootOrder from output
+ ansible.builtin.set_fact:
+ data: "{{ result_data.json.Boot.BootOrder | default([]) }}"
+
+ - name: Reversing the boot order
+ ansible.builtin.set_fact:
+ reverse_boot_order: "{{ data | reverse | list }}"
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure boot mode is legacy
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_mode: legacy
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115427 - Validate boot_order with legacy mode with force_restart
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_order: "{{ reverse_boot_order }}"
+ reset_type: force_restart
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115427 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115427 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Successfully updated the boot settings."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115427 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_legacy_mode_force_restart/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/converge.yml
new file mode 100644
index 000000000..58cd441fe
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/converge.yml
@@ -0,0 +1,120 @@
+---
+- name: Testing boot_order_using_uefi_mode_graceful_restart
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_order_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1/"
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Fetching boot order from iDRAC
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ boot_order_uri }}"
+ method: GET
+ register: result_data
+ check_mode: false
+ no_log: true
+
+ - name: Extracing BootOrder from output
+ ansible.builtin.set_fact:
+ data: "{{ result_data.json.Boot.BootOrder | default([]) }}"
+
+ - name: Reversing the boot order
+ ansible.builtin.set_fact:
+ reverse_boot_order: "{{ data | reverse | list }}"
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure boot mode is uefi
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_mode: uefi
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115428 - Validate boot_order with uefi mode with graceful_restart
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_order: "{{ reverse_boot_order }}"
+ reset_type: graceful_restart
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115428 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115428 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Successfully updated the boot settings."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115428 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_order_using_uefi_mode_graceful_restart/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/converge.yml
new file mode 100644
index 000000000..076cdd755
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/converge.yml
@@ -0,0 +1,102 @@
+---
+- name: Testing boot_source_override_enabled_as_continuous_reset_type_none
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure boot_source_override_enabled is disabled
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_enabled: disabled
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115433 - Validate boot_source_override_enabled as continuous
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_enabled: continuous
+ reset_type: none
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115433 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115433 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "The boot settings job is triggered successfully."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115433 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_continuous_reset_type_none/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/converge.yml
new file mode 100644
index 000000000..8c8d2d443
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/converge.yml
@@ -0,0 +1,102 @@
+---
+- name: Testing boot_source_override_enabled_as_disabled_reset_type_none
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure boot_source_override_enabled is continuous
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_enabled: continuous
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115431 - Validate boot_source_override_enabled as disabled
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_enabled: disabled
+ reset_type: none
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115431 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115431 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "The boot settings job is triggered successfully."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115431 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_disabled_reset_type_none/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/converge.yml
new file mode 100644
index 000000000..50bb281b2
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/converge.yml
@@ -0,0 +1,102 @@
+---
+- name: Testing boot_source_override_enabled_as_once_reset_type_none
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure boot_source_override_enabled is disabled
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_enabled: disabled
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115432 - Validate boot_source_override_enabled as once
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_enabled: once
+ reset_type: none
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115432 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115432 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "The boot settings job is triggered successfully."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115432 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_enabled_as_once_reset_type_none/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/converge.yml
new file mode 100644
index 000000000..86b7b39ea
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/converge.yml
@@ -0,0 +1,116 @@
+---
+- name: Testing boot_source_override_mode_legacy_job_wait_false
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ job_status_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Managers/iDRAC.Embedded.1/Jobs"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure boot mode is uefi
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_mode: uefi
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115429 - Validate boot_source_override_mode as legacy with job_wait false
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_mode: legacy
+ job_wait: false
+
+ - name: Job tracking after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ job_status_uri }}/{{ idrac_boot_out.job.Id }}"
+ method: GET
+ register: job_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: job_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115429 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115429 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "The boot settings job is triggered successfully."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115429 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_legacy_job_wait_false/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/converge.yml
new file mode 100644
index 000000000..a2b6ef922
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/converge.yml
@@ -0,0 +1,129 @@
+---
+- name: Testing boot_source_override_mode_uefi_with_resource_id
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ system_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems"
+ lc_uri: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ retry_count: 60
+ delay_count: 30
+ tasks:
+ - name: Preparing set_fact for uri
+ ansible.builtin.set_fact:
+ uri_input: &uri_input
+ user: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ return_content: true
+ force_basic_auth: true
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+ - name: Fetching resource_id from iDRAC
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ system_uri }}"
+ method: GET
+ register: result_data
+ check_mode: false
+ no_log: true
+
+ - name: Extracting resource_id from output
+ ansible.builtin.set_fact:
+ resource_id_data: "{{ result_data.json.Members[0]['@odata.id'] | split('/') | last }}"
+
+ - name: Checking for LCStatus before running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Pre-requisite - Making sure boot mode is legacy
+ check_mode: false
+ ansible.builtin.import_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_mode: legacy
+ tags: molecule-idempotence-notest
+
+ - name: Checking for LCStatus after running pre-requisite
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: TC-115430 - Validate boot_source_override_mode as uefi with resource_id
+ ansible.builtin.include_role:
+ name: "idrac_boot"
+ vars:
+ boot_source_override_mode: uefi
+ resource_id: "{{ resource_id_data }}"
+
+ - name: Job tracking after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ job_status_uri }}/{{ idrac_boot_out.job.Id }}"
+ method: GET
+ register: job_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: job_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Checking for LCStatus after performing operation
+ ansible.builtin.uri:
+ <<: *uri_input
+ url: "{{ lc_uri }}"
+ method: POST
+ body: {}
+ register: lc_status_result
+ check_mode: false
+ when: idrac_boot_out.changed # noqa: no-handler
+ until: lc_status_result.json.LCStatus == "Ready"
+ retries: "{{ retry_count }}"
+ delay: "{{ delay_count }}"
+ no_log: true
+
+ - name: Asserting TC-115430 in check mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting TC-115430 in normal mode
+ ansible.builtin.assert:
+ that: idrac_boot_out.msg == "The boot settings job is triggered successfully."
+ when: not ansible_check_mode and idrac_boot_out.changed
+
+ - name: Asserting TC-115430 in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_boot_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/boot_source_override_mode_uefi_with_resource_id/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/converge.yml
new file mode 100644
index 000000000..08e7ab3be
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/converge.yml
@@ -0,0 +1,311 @@
+---
+- name: Play 1 - Negative Scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Play 1 - TC-115436 - Ansible - Role - idrac_boot - Providing wrong hostname
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "WrongHostname"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_source_override_mode: 'uefi'
+ ignore_unreachable: true
+
+ - name: Verify - TC-115436 - Ansible - Role - idrac_boot - Providing wrong hostname
+ ansible.builtin.assert:
+ that:
+ - "'Unable to communicate with iDRAC WrongHostname' in idrac_boot_out.msg"
+
+ - name: TC-115437 - Ansible - Role - idrac_boot - Providing wrong username
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "wrongUsername"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_source_override_mode: 'uefi'
+ register: idrac_boot_error_reg
+ ignore_errors: true
+
+ - name: Verify - TC-115437 - Ansible - Role - idrac_boot - Providing wrong username
+ ansible.builtin.assert:
+ that:
+ - "'Unable to communicate with iDRAC' in idrac_boot_out.msg"
+
+ - name: TC-115438 - Ansible - Role - idrac_boot - Providing wrong password
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "wrongPassword"
+ validate_certs: false
+ boot_source_override_mode: 'uefi'
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_boot_error_reg
+
+ - name: Verify - TC-115438 - Ansible - Role - idrac_boot - Providing wrong password
+ ansible.builtin.assert:
+ that:
+ - "'Unable to communicate with iDRAC' in idrac_boot_out.msg"
+
+- name: Play 2 - TC-115439 - Ansible - Role - idrac_boot - Providing invalid https_port
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: TC-115439 - Ansible - Role - idrac_boot - Providing invalid https_port
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ https_port: 999999
+ validate_certs: false
+ boot_source_override_mode: 'uefi'
+ ignore_unreachable: true
+
+ - name: Verify - TC-115439 - Ansible - Role - idrac_boot - Providing invalid https_port
+ ansible.builtin.assert:
+ that:
+ - "'Unable to communicate with iDRAC' in idrac_boot_out.msg"
+
+- name: Play 3 - TC-115440 - Ansible - Role - idrac_boot - Providing wrong resource_id
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: TC-115440 - Ansible - Role - idrac_boot - Providing wrong resource_id
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ resource_id: "Invalid.System.ID"
+ validate_certs: false
+ boot_source_override_mode: 'uefi'
+ ignore_errors: true
+ register: idrac_boot_error_reg
+
+ - name: Verify - TC-115440 - Ansible - Role - idrac_boot - Providing wrong resource_id
+ ansible.builtin.assert:
+ that:
+ - "'HTTP Error 404' in idrac_boot_out.msg"
+
+- name: Play 4 - TC-115441 - Ansible - Role - idrac_boot - Providing wrong ca_path
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: TC-115441 - Ansible - Role - idrac_boot - Providing wrong ca_path
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ ca_path: "/root/filenotexists.pem"
+ validate_certs: false
+ boot_source_override_mode: 'uefi'
+ ignore_errors: true
+ register: idrac_boot_error_reg
+
+ - name: Verify - TC-115441 - Ansible - Role - idrac_boot - Providing wrong ca_path
+ ansible.builtin.assert:
+ that:
+ - idrac_boot_out.failed # TBD
+
+- name: Play 5 - TC-115442 - Ansible - Role - idrac_boot - Providing invalid https_timeout
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: TC-115442 - Ansible - Role - idrac_boot - Providing invalid https_timeout
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ https_timeout: -1000
+ validate_certs: false
+ boot_source_override_mode: 'uefi'
+ ignore_errors: true
+ register: idrac_boot_error_reg
+
+ - name: Verify - TC-115442 - Ansible - Role - idrac_boot - Providing invalid https_timeout
+ ansible.builtin.assert:
+ that:
+ - "'Timeout value out of range' == idrac_boot_out.msg"
+
+- name: Play 6 - TC-115443 - Ansible - Role - idrac_boot - Providing invalid job_wait_timeout
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: TC-115443 - Ansible - Role - idrac_boot - Providing invalid job_wait_timeout
+ block:
+ - name: TC-115443 - Ansible - Role - idrac_boot - Providing invalid job_wait_timeout
+ ansible.builtin.import_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ job_wait_timeout: -1000
+ validate_certs: false
+ boot_source_override_mode: 'legacy'
+ register: idrac_boot_error_reg
+ rescue:
+ - name: Verify - TC-115443 - Ansible - Role - idrac_boot - Providing invalid job_wait_timeout
+ ansible.builtin.assert:
+ that:
+ - "'The parameter job_wait_timeout value cannot be negative or zero.' == ansible_failed_result.msg"
+
+- name: Play 7 - TC-115444 - Ansible - Role - idrac_boot - Validate all the mutually exclusive scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Check 1 - TC-115444 - Entering block
+ block:
+ - name: Check 1 - TC-115444 - mutual exclusivity between boot_option_reference and display_name
+ ansible.builtin.include_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_options:
+ - display_name: Hard drive C
+ boot_option_reference: NIC.PxeDevice.2-1
+ enabled: true
+ ignore_errors: true
+ register: idrac_boot_error_reg
+ rescue:
+ - name: Verify - Check 1 - TC-115444 - mutual exclusivity between boot_option_reference and display_name
+ ansible.builtin.assert:
+ that:
+ - "'parameters are mutually exclusive' in idrac_boot_out.msg"
+ - "'boot_option_reference' in idrac_boot_out.msg"
+ - "'display_name' in idrac_boot_out.msg"
+ - idrac_boot_out.failed
+
+ - name: Check 2 - TC-115444 - Entering block
+ block:
+ - name: Check 2 - TC-115444 - mutual exclusivity between boot_options and boot_order
+ ansible.builtin.include_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_options:
+ - display_name: Hard drive C
+ enabled: true
+ boot_order:
+ - Boot0001
+ - Boot0002
+ ignore_errors: true
+ register: idrac_boot_error_reg
+ rescue:
+ - name: Verify - Check 2 - TC-115444 - mutual exclusivity between boot_options and boot_order
+ ansible.builtin.assert:
+ that: >
+ "'parameters are mutually exclusive: boot_options|boot_order found in
+ boot_options' == idrac_boot_out.msg"
+
+ - name: Check 3 - TC-115444 - Entering block
+ block:
+ - name: Check 3 - TC-115444 - mutual exclusivity between boot_options and boot_source_override_mode
+ ansible.builtin.include_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_options:
+ - display_name: Hard drive C
+ enabled: true
+ boot_source_override_mode: legacy
+ ignore_errors: true
+ register: idrac_boot_error_reg
+ rescue:
+ - name: Verify - Check 3 - TC-115444 - mutual exclusivity between boot_options and boot_source_override_mode
+ ansible.builtin.assert:
+ that: >
+ "'parameters are mutually exclusive: boot_options|boot_source_override_mode found in
+ boot_options' == idrac_boot_out.msg"
+
+ - name: Check 4 - TC-115444 - Entering block
+ block:
+ - name: Check 4 - TC-115444 - mutual exclusivity between boot_options and boot_source_override_enabled
+ ansible.builtin.include_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_options:
+ - display_name: Hard drive C
+ enabled: true
+ boot_source_override_enabled: once
+ ignore_errors: true
+ register: idrac_boot_error_reg
+ rescue:
+ - name: Verify - Check 4 - TC-115444 - mutual exclusivity between boot_options and boot_source_override_enabled
+ ansible.builtin.assert:
+ that: >
+ "'parameters are mutually exclusive: boot_options|boot_source_override_enabled found in
+ boot_options' == idrac_boot_out.msg"
+
+ - name: Check 5 - TC-115444 - Entering block
+ block:
+ - name: Check 5 - TC-115444 - mutual exclusivity between boot_options and boot_source_override_target
+ ansible.builtin.include_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_options:
+ - display_name: Hard drive C
+ enabled: true
+ boot_source_override_target: cd
+ ignore_errors: true
+ register: idrac_boot_error_reg
+ rescue:
+ - name: Verify - Check 5 - TC-115444 - mutual exclusivity between boot_options and boot_source_override_target
+ ansible.builtin.assert:
+ that: >
+ "'parameters are mutually exclusive: boot_options|boot_source_override_target found in
+ boot_options' == idrac_boot_out.msg"
+
+ - name: Check 6 - TC-115444 - Entering block
+ block:
+ - name: Check 6 - TC-115444 - mutual exclusivity between boot_options and uefi_target_boot_source_override
+ ansible.builtin.include_role:
+ name: idrac_boot
+ vars:
+ hostname: "{{ lookup('ansible.builtin.env', 'IDRAC_IP') }}"
+ username: "{{ lookup('ansible.builtin.env', 'IDRAC_USER') }}"
+ password: "{{ lookup('ansible.builtin.env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ boot_options:
+ - display_name: Hard drive C
+ enabled: true
+ uefi_target_boot_source_override: "VenHw(3A191845-5F86-4E78-8FCE-C4CFF59F9DAA)"
+ ignore_errors: true
+ register: idrac_boot_error_reg
+ rescue:
+ - name: Verify - Check 6 - TC-115444 - mutual exclusivity between boot_options and uefi_target_boot_source_override
+ ansible.builtin.assert:
+ that: >
+ "'parameters are mutually exclusive: boot_options|uefi_target_boot_source_override found in
+ boot_options' == idrac_boot_out.msg"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/molecule.yml
new file mode 100644
index 000000000..fbbe91b9c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/molecule/default/molecule.yml
@@ -0,0 +1,9 @@
+---
+scenario:
+ test_sequence:
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/tasks/main.yml
new file mode 100644
index 000000000..78047aa51
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/tasks/main.yml
@@ -0,0 +1,27 @@
+---
+- name: Fail when job_wait_timeout is negative.
+ ansible.builtin.fail:
+ msg: "{{ idrac_boot_job_wait_timeout_err }}"
+ when: job_wait_timeout < 1
+
+- name: Configure the system boot settings
+ dellemc.openmanage.idrac_boot:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ https_timeout }}"
+ boot_options: "{{ boot_options | default(omit) }}"
+ boot_order: "{{ boot_order | default(omit) }}"
+ boot_source_override_mode: "{{ boot_source_override_mode | default(omit) }}"
+ boot_source_override_enabled: "{{ boot_source_override_enabled | default(omit) }}"
+ boot_source_override_target: "{{ boot_source_override_target | default(omit) }}"
+ uefi_target_boot_source_override: "{{ uefi_target_boot_source_override | default(omit) }}"
+ reset_type: "{{ reset_type }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ resource_id: "{{ resource_id | default(omit) }}"
+ register: idrac_boot_out
+ delegate_to: "{{ idrac_boot_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/test.yml
new file mode 100644
index 000000000..f043a741f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Testing for idrac boot
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_boot
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_boot/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_boot/vars/main.yml
new file mode 100644
index 000000000..55198828b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_boot/vars/main.yml
@@ -0,0 +1,3 @@
+---
+idrac_boot_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+idrac_boot_job_wait_timeout_err: "The parameter job_wait_timeout value cannot be negative or zero."
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/README.md
new file mode 100644
index 000000000..30f8f8008
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/README.md
@@ -0,0 +1,386 @@
+# idrac_certificate
+
+Role to manage the iDRAC certificates - Generate Certificate Signing Request, Import/Export certificates, and Reset configuration - for PowerEdge servers.
+
+## Requirements
+
+---
+
+Requirements to develop and contribute to the role.
+
+### Development
+
+```
+ansible
+docker
+molecule
+python
+```
+
+### Production
+
+Requirements to use the role.
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+---
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>command</td>
+ <td>false</td>
+ <td>generate_csr</td>
+ <td>'import', 'export', 'generate_csr', 'reset'</td>
+ <td>str</td>
+ <td>- C(generate_csr), generate CSR. This requires I(cert_params) and I(certificate_path).
+ <br>- C(import), import the certificate file. This requires I(certificate_path).
+ <br>- C(export), export the certificate. This requires I(certificate_path).
+ <br>- C(reset), reset the certificate to default settings. This is applicable only for C(HTTPS).
+ </td>
+ </tr>
+ <tr>
+ <td>certificate_type</td>
+ <td>false</td>
+ <td>HTTPS</td>
+ <td>'HTTPS', 'CA', 'CSC', 'CLIENT_TRUST_CERTIFICATE', 'CUSTOMCERTIFICATE'</td>
+ <td>str</td>
+ <td>-Type of the iDRAC certificate:
+ <br>- C(HTTPS) The Dell self-signed SSL certificate.
+ <br>- C(CA) Certificate Authority(CA) signed SSL certificate.
+ <br>- C(CSC) The custom signed SSL certificate.
+ <br>- C(CLIENT_TRUST_CERTIFICATE) Client trust certificate.
+ <br>- C(CUSTOMCERTIFICATE) The custom PKCS12 certificate and private key. Export of custom certificate is supported only on iDRAC firmware version 7.00.00.00 and above.</td>
+ </tr>
+ <tr>
+ <td>certificate_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- Absolute path of the certificate file if I(command) is C(import).
+ <br>- Directory path with write permissions if I(command) is C(generate_csr) or C(export).<br></td>
+ </tr>
+ <tr>
+ <td>passpharse</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The passphrase string if the certificate to be imported is passphrase protected.</td>
+ </tr>
+ <tr>
+ <td>ssl_key</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- Absolute path of the private or SSL key file.
+ <br>- This is applicable only when I(command) is C(import) and I(certificate_type) is C(HTTPS).
+ <br>- Uploading the SSL key on iDRAC is supported on version 6.00.02.00 and newer versions.<br></td>
+ </tr>
+ <tr>
+ <td>cert_params</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;common_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The common name of the certificate.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;organization_unit</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>str</td>
+ <td>- The name associated with an organizational unit. For example, department name.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;locality_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The city or other location where the entity applying for certification is located.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The state where the entity applying for certification is located.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;country_code</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td> - The country code of the country where the entity applying for certification is located.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;email_address</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The email associated with the CSR.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;organization_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The name associated with an organization.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subject_alt_name</td>
+ <td>false</td>
+ <td>[]</td>
+ <td></td>
+ <td>list</td>
+ <td>- The alternative domain names associated with the request.</td>
+ </tr>
+ <tr>
+ <td>resource_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Redfish ID of the resource.</td>
+ </tr>
+ <tr>
+ <td>reset</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>- To reset the iDRAC after the certificate operation.<br>- This is applicable when I(command) is C(import) or C(reset).<br></td>
+ </tr>
+ <tr>
+ <td>wait</td>
+ <td>false</td>
+ <td>300</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Maximum wait time for iDRAC to start after the reset, in seconds.<br>- This is applicable when I(command) is C(import) or C(reset) and I(reset) is C(True).<br></td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_certificate_out</td>
+ <td>{
+"certificate_path": "/root/Certs/192.168.0.1_202333_4130_HTTPS.pem",
+ "changed": false,
+ "msg": "Successfully performed the 'export' operation."
+}</td>
+ <td>Module output of the cerificate export job.</td>
+ </tr>
+ </tbody>
+</table>
+
+## Examples
+
+---
+
+```
+- name: Generate HTTPS certificate signing request
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ command: "generate_csr"
+ certificate_type: "HTTPS"
+ certificate_path: "/home/omam/mycerts"
+ cert_params:
+ common_name: "sample.domain.com"
+ organization_unit: "OrgUnit"
+ locality_name: "Bangalore"
+ state_name: "Karnataka"
+ country_code: "IN"
+ email_address: "admin@domain.com"
+ organization_name: "OrgName"
+ subject_alt_name:
+ - 192.198.2.1
+```
+
+```
+- name: Importing certificate.
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ command: "import"
+ certificate_type: "HTTPS"
+ certificate_path: "/path/to/cert.pem"
+```
+
+```
+- name: Exporting certificate.
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ command: "export"
+ certificate_type: "HTTPS"
+ certificate_path: "/home/omam/mycert_dir"
+```
+
+```
+- name: Importing Custom Signing Certificate.
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ command: "import"
+ certificate_type: "CSC"
+ certificate_path: "/path/to/cert.pem"
+```
+
+```
+- name: Import an HTTPS certificate with private key.
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ command: "import"
+ certificate_type: "HTTPS"
+ certificate_path: "/path/to/cert.pem"
+ ssl_key: "/path/to/ssl_key"
+```
+
+```
+- name: Exporting certificate.
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ command: "export"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "/home/omam/mycert_dir"
+```
+
+## Author Information
+---
+Dell Technologies <br>
+Shivam Sharma (Shivam.Sharma3@Dell.com) 2023<br>
+Jagadeesh N V (Jagadeesh.N.V@Dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/defaults/main.yml
new file mode 100644
index 000000000..5c3acbfe1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/defaults/main.yml
@@ -0,0 +1,10 @@
+---
+# defaults file for idrac_certificate
+
+https_port: 443
+validate_certs: true
+https_timeout: 30
+certificate_type: "HTTPS"
+command: generate_csr
+reset: true
+wait: 300
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/handlers/main.yml
new file mode 100644
index 000000000..edfc1a30b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_certificate
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/argument_specs.yml
new file mode 100644
index 000000000..9b1220ae5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/argument_specs.yml
@@ -0,0 +1,132 @@
+---
+argument_specs:
+ main:
+ version_added: "7.4.0"
+ short_description: This role allows to generate certificate signing
+ request, import, and export certificates on iDRAC
+ description:
+ - Role to manage the iDRAC certificates - Generate CSR,
+ Import/Export certificates, and Reset configuration - for
+ PowerEdge servers.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ username:
+ type: str
+ description: iDRAC username.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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.
+ - Prior to collection version C(5.0.0), the I(validate_certs) is
+ C(false) by default.
+ type: bool
+ default: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a
+ CA certificate to be used for the validation.
+ type: str
+ https_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ command:
+ description: C(generate_csr), generate CSR. This requires
+ I(cert_params) and I(certificate_path).
+ choices: ["import", "export", "generate_csr", "reset"]
+ default: "generate_csr"
+ type: str
+ certificate_type:
+ description: Type of the iDRAC certificate
+ - C(HTTPS) The Dell self-signed SSL certificate.
+ - C(CA) Certificate Authority(CA) signed SSL certificate.
+ - C(CSC) The custom signed SSL certificate.
+ - C(CLIENT_TRUST_CERTIFICATE) Client trust certificate.
+ - C(CUSTOMCERTIFICATE) The custom PKCS12 certificate and private key.
+ Export of custom certificate is supported only on
+ iDRAC firmware version 7.00.00.00 and above.
+ type: str
+ choices: ["HTTPS", "CA", "CSC", "CLIENT_TRUST_CERTIFICATE",
+ "CUSTOMCERTIFICATE"]
+ default: "HTTPS"
+ certificate_path:
+ description:
+ - Absolute path of the certificate file if I(command) is C(import).
+ - Directory path with write permissions if I(command)
+ is C(generate_csr) or C(export).
+ type: path
+ passphrase:
+ description: The passphrase string if the certificate to be
+ imported is passphrase protected.
+ type: str
+ ssl_key:
+ description:
+ - Absolute path of the private or SSL key file.
+ - This is applicable only when I(command) is C(import)
+ and I(certificate_type) is C(HTTPS).
+ - Uploading the SSL key on iDRAC is supported on version
+ 6.00.02.00 and newer versions.
+ type: path
+ version_added: 8.6.0
+ cert_params:
+ description: Certificate parameters to generate signing request.
+ type: dict
+ options:
+ common_name:
+ description: The common name of the certificate.
+ type: str
+ organization_unit:
+ description: The name associated with an organizational unit.
+ For example, department name.
+ type: str
+ default: true
+ locality_name:
+ description: The city or other location where the entity
+ applying for certification is located.
+ type: str
+ state_name:
+ description: The state where the entity applying for
+ certification is located.
+ type: str
+ country_code:
+ description: The country code of the country where the entity
+ applying for certification is located.
+ type: str
+ email_address:
+ description: The email associated with the CSR.
+ type: str
+ organization_name:
+ description: The name associated with an organization.
+ type: str
+ subject_alt_name:
+ description: The alternative domain names associated with the request.
+ type: list
+ elements: str
+ default: []
+ resource_id:
+ description: Redfish ID of the resource.
+ type: str
+ reset:
+ description:
+ - To reset the iDRAC after the certificate operation.
+ - This is applicable when I(command) is C(import) or C(reset).
+ type: bool
+ default: true
+ wait:
+ description:
+ - Maximum wait time for iDRAC to start after the reset, in seconds.
+ - This is applicable when I(command) is C(import) or C(reset)
+ and I(reset) is C(True).
+ type: int
+ default: 300
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/main.yml
new file mode 100644
index 000000000..d6a65cf69
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/meta/main.yml
@@ -0,0 +1,22 @@
+galaxy_info:
+ author: |
+ "Shivam Sharma
+ Jagadeesh N V"
+ description: Role to manage the iDRAC certificates - Generate CSR, Import/Export certificates, and Reset configuration - for PowerEdge servers.
+ company: Dell Technologies
+ license: GPL-3.0-only
+ min_ansible_version: "2.13"
+ platforms:
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/converge.yml
new file mode 100644
index 000000000..64e2a242f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/converge.yml
@@ -0,0 +1,90 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ ca_cert_name: "{{ lookup('env', 'ca_cert_name') }}"
+ import_cert_path: "{{ lookup('env', 'path_for_import_cert') }}"
+ export_cert_path: "{{ lookup('env', 'path_for_export_cert') }}"
+ idrac_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Fetching CA certificate from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ ca_cert_name }}"
+
+ - name: Import CA certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CA"
+ certificate_path: "{{ import_cert_path }}{{ ca_cert_name }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 30
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'import' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ - name: Export CA certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "export"
+ certificate_type: "CA"
+ certificate_path: "{{ export_cert_path }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+ when: not ansible_check_mode
+
+ - name: Setting up CA certificate path for exported file
+ when: idrac_certificate_out is defined
+ and idrac_certificate_out.certificate_path is defined
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: ca_cert_file
+ delegate_to: "{{ idrac_delegate_to }}"
+ no_log: true
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that:
+ - ca_cert_file.stat.exists
+ - not idrac_certificate_out.changed
+ - not idrac_certificate_out.failed
+ - idrac_certificate_out.msg == "Successfully performed the
+ 'export' certificate operation."
+ when: not ansible_check_mode and not idrac_certificate_out.changed
+
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CA/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/converge.yml
new file mode 100644
index 000000000..2a8708f27
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/converge.yml
@@ -0,0 +1,168 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ csc_cert_name: "{{ lookup('env', 'csc_certificate') }}"
+ csc_cert_pass_name: "{{ lookup('env', 'csc_passphrase_certificate') }}"
+ import_cert_path: "{{ lookup('env', 'path_for_import_cert') }}"
+ export_cert_path: "{{ lookup('env', 'path_for_export_cert') }}"
+ idrac_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Fetching CSC certificates from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ csc_cert_name }}"
+
+ - name: Import CSC certificate without passphrase
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CSC"
+ passphrase: ""
+ certificate_path: "{{ import_cert_path }}{{ csc_cert_name }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 30
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'import' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ - name: Export CSC certificate without passphrase
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "export"
+ certificate_type: "CSC"
+ certificate_path: "{{ export_cert_path }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+ when: not ansible_check_mode
+
+ - name: Setting up CSC certificate path for exported file
+ when: idrac_certificate_out is defined
+ and idrac_certificate_out.certificate_path is defined
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: csc_cert_file
+ delegate_to: "{{ idrac_delegate_to }}"
+ no_log: true
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that:
+ - csc_cert_file.stat.exists
+ - not idrac_certificate_out.changed
+ - not idrac_certificate_out.failed
+ - idrac_certificate_out.msg == "Successfully performed the
+ 'export' certificate operation."
+ when: not ansible_check_mode and not idrac_certificate_out.changed
+
+ - name: Fetching CSC certificates from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ csc_cert_pass_name }}"
+
+ - name: Import CSC certificate with passphrase
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CSC"
+ passphrase: "{{ lookup('env', 'passphrase') }}"
+ certificate_path: "{{ import_cert_path }}{{ csc_cert_pass_name }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 30
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'import' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ - name: Export CSC certificate with passphrase
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "export"
+ certificate_type: "CSC"
+ certificate_path: "{{ export_cert_path }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+ when: not ansible_check_mode
+
+ - name: Setting up CSC certificate path for exported file
+ when: idrac_certificate_out is defined
+ and idrac_certificate_out.certificate_path is defined
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: csc_cert_file
+ delegate_to: "{{ idrac_delegate_to }}"
+ no_log: true
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that:
+ - csc_cert_file.stat.exists
+ - not idrac_certificate_out.changed
+ - not idrac_certificate_out.failed
+ - idrac_certificate_out.msg == "Successfully performed the
+ 'export' certificate operation."
+ when: not ansible_check_mode and not idrac_certificate_out.changed
+
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CSC/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/converge.yml
new file mode 100644
index 000000000..cdf53ff08
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/converge.yml
@@ -0,0 +1,90 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ ctc_cert_name: "{{ lookup('env', 'ctc_cert_name') }}"
+ import_cert_path: "{{ lookup('env', 'path_for_import_cert') }}"
+ export_cert_path: "{{ lookup('env', 'path_for_export_cert') }}"
+ idrac_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Fetching CTC certificate from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ ctc_cert_name }}"
+
+ - name: Import CTC certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "{{ import_cert_path }}{{ ctc_cert_name }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 30
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'import' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ - name: Export CTC certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "export"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "{{ export_cert_path }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+ when: not ansible_check_mode
+
+ - name: Setting up CTC certificate path for exported file
+ when: idrac_certificate_out is defined
+ and idrac_certificate_out.certificate_path is defined
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: ctc_cert_file
+ delegate_to: "{{ idrac_delegate_to }}"
+ no_log: true
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that:
+ - ctc_cert_file.stat.exists
+ - not idrac_certificate_out.changed
+ - not idrac_certificate_out.failed
+ - idrac_certificate_out.msg == "Successfully performed the
+ 'export' certificate operation."
+ when: not ansible_check_mode and not idrac_certificate_out.changed
+
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CTC/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/converge.yml
new file mode 100644
index 000000000..0f07f68ca
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/converge.yml
@@ -0,0 +1,207 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ custom_certificate_failure: {}
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ custom_cert_name: "{{ lookup('env', 'custom_cert_name') }}"
+ cust_crt_name_pass: "{{ lookup('env', 'custom_cert_name_pass') }}"
+ import_cert_path: "{{ lookup('env', 'path_for_import_cert') }}"
+ idrac_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Fetching firmware version for IDRAC
+ ansible.builtin.include_tasks:
+ file: ../__extract_firmware_version.yml
+ vars:
+ idrac_ip: "{{ lookup('env', 'hostname') }}"
+ idrac_user: "{{ lookup('env', 'username') }}"
+ idrac_password: "{{ lookup('env', 'password') }}"
+
+ - name: Set expected firmware version
+ ansible.builtin.set_fact:
+ firmware_version_expected: "6.10.80.00"
+ firmware_version_expected_export: "7.00.00.00"
+
+ - name: Import CUSTOMCERTIFICATE without passphrase
+ when: idrac_certificate_firmware_version is defined and
+ "idrac_certificate_firmware_version >= firmware_version_expected"
+ and custom_cert_name
+ block:
+ - name: Fetching Custom certificate from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ custom_cert_name }}"
+
+ - name: Import a custom certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CUSTOMCERTIFICATE"
+ certificate_path: "{{ import_cert_path }}{{ custom_cert_name }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+ passphrase: ""
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 60
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'import' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ rescue:
+ - name: Set the failure messages for CUSTOMECERT
+ ansible.builtin.set_fact:
+ custom_certificate_failure: "{{ custom_certificate_failure |
+ combine({'CUSTOMCERTIFICATE_WITHOUT_PASS_IMPORT':
+ {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+ always:
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
+
+ - name: Export CUSTOMCERTIFICATE
+ when:
+ - idrac_certificate_firmware_version is defined
+ - "idrac_certificate_firmware_version >=
+ firmware_version_expected_export"
+ block:
+ - name: Fetching Custom certificate from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+
+ - name: Export a custom certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "export"
+ certificate_type: "CUSTOMCERTIFICATE"
+ certificate_path: "{{ import_cert_path }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+ when: not ansible_check_mode
+
+ - name: Setting up CustomCertificate certificate path for exported file
+ when: idrac_certificate_out is defined
+ and idrac_certificate_out.certificate_path is defined
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: csc_cert_file
+ delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+ no_log: true
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that:
+ - csc_cert_file.stat.exists
+ - not idrac_certificate_out.changed
+ - not idrac_certificate_out.failed
+ - idrac_certificate_out.msg == "Successfully performed the
+ 'export' certificate operation."
+ when: not ansible_check_mode and not idrac_certificate_out.changed
+
+ rescue:
+ - name: Set the failure messages for CUSTOMECERT
+ ansible.builtin.set_fact:
+ custom_certificate_failure: "{{ custom_certificate_failure |
+ combine({'CUSTOMCERTIFICATE_EXPORT':
+ {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
+
+ - name: Import CUSTOMCERTIFICATE with passphrase
+ when: idrac_certificate_firmware_version is defined and
+ "idrac_certificate_firmware_version >= firmware_version_expected"
+ and cust_crt_name_pass
+ block:
+ - name: Fetching Custom certificate from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ cust_crt_name_pass }}"
+
+ - name: Import a custom certificate with passphrase
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CUSTOMCERTIFICATE"
+ certificate_path: "{{ import_cert_path }}{{ cust_crt_name_pass }}"
+ passphrase: "{{ lookup('env', 'passphrase') }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 60
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'import' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ rescue:
+ - name: Set the failure messages for CUSTOMECERT
+ ansible.builtin.set_fact:
+ custom_certificate_failure: "{{ custom_certificate_failure |
+ combine({'CUSTOMCERTIFICATE_WITH_PASS_IMPORT':
+ {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: custom_certificate_failure
+ when: custom_certificate_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/CustomCertificate/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/converge.yml
new file mode 100644
index 000000000..28cdf16b8
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/converge.yml
@@ -0,0 +1,90 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ https_cert_name: "{{ lookup('env', 'https_cert_name') }}"
+ import_cert_path: "{{ lookup('env', 'path_for_import_cert') }}"
+ export_cert_path: "{{ lookup('env', 'path_for_export_cert') }}"
+ idrac_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Fetching HTTPS certificate from share
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ https_cert_name }}"
+
+ - name: Import HTTPS certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "HTTPS"
+ certificate_path: "{{ import_cert_path }}{{ https_cert_name }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 30
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'import' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ - name: Export a custom certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "export"
+ certificate_type: "HTTPS"
+ certificate_path: "{{ export_cert_path }}"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+ when: not ansible_check_mode
+
+ - name: Setting up HTTPS certificate path for exported file
+ when: idrac_certificate_out is defined
+ and idrac_certificate_out.certificate_path is defined
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: https_cert_file
+ delegate_to: "{{ idrac_delegate_to }}"
+ no_log: true
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that:
+ - https_cert_file.stat.exists
+ - not idrac_certificate_out.changed
+ - not idrac_certificate_out.failed
+ - idrac_certificate_out.msg == "Successfully performed the
+ 'export' certificate operation."
+ when: not ansible_check_mode and not idrac_certificate_out.changed
+
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/HTTPS/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/converge.yml
new file mode 100644
index 000000000..c90e4e53e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/converge.yml
@@ -0,0 +1,94 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ https_cert_ssl_failure: {}
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ path_for_import_cert: "{{ lookup('env', 'path_for_import_cert') }}"
+ idrac_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Fetching firmware version for IDRAC
+ ansible.builtin.include_tasks:
+ file: ../__extract_firmware_version.yml
+ vars:
+ idrac_ip: "{{ lookup('env', 'hostname') }}"
+ idrac_user: "{{ lookup('env', 'username') }}"
+ idrac_password: "{{ lookup('env', 'password') }}"
+
+ - name: Set expected firmware version
+ ansible.builtin.set_fact:
+ firmware_version_expected: "6.00.02.00"
+
+ - name: Import Https certificate using ssl_key
+ when: idrac_certificate_firmware_version is defined and
+ "idrac_certificate_firmware_version >= firmware_version_expected"
+ block:
+ - name: Create directory
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+
+ - name: Create SSL Key ans self-signed certificate
+ when: idrac_certificate_check_file_created.stat.exists
+ ansible.builtin.include_tasks:
+ file: ../__get_ssl_key.yml
+
+ - name: Importing HTTPS certificate using ssl_key
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "HTTPS"
+ certificate_path: "{{ path_for_import_cert }}cert.pem"
+ ssl_key: "{{ path_for_import_cert }}cert.key"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Waiting for idrac readiness
+ ansible.builtin.wait_for:
+ timeout: 60
+ when:
+ - not ansible_check_mode
+ - idrac_certificate_out is defined
+ - idrac_certificate_out.changed
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the SSL
+ key upload and 'import' certificate operation.
+ iDRAC has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not idrac_certificate_out.changed
+
+ rescue:
+ - name: Set the failure messages for SSLKEY
+ ansible.builtin.set_fact:
+ https_cert_ssl_failure: "{{ https_cert_ssl_failure |
+ combine({'HTTPS_SSL_KEY_CERT_IMPORT':
+ {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: https_cert_ssl_failure
+ when: https_cert_ssl_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/SSLKEY/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__delete_directory.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__delete_directory.yml
new file mode 100644
index 000000000..d301ea290
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__delete_directory.yml
@@ -0,0 +1,6 @@
+---
+- name: Delete the directory
+ ansible.builtin.file:
+ path: "{{ lookup('env', 'path_for_import_cert') }}"
+ state: absent
+ delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__extract_firmware_version.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__extract_firmware_version.yml
new file mode 100644
index 000000000..9ffc8b8df
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__extract_firmware_version.yml
@@ -0,0 +1,21 @@
+---
+- name: Fetch firmware version
+ ansible.builtin.uri:
+ url: "https://{{ idrac_ip }}/redfish/v1/Managers/iDRAC.Embedded.1"
+ user: "{{ idrac_user }}"
+ password: "{{ idrac_password }}"
+ method: GET
+ force_basic_auth: true
+ validate_certs: false
+ body_format: json
+ return_content: true
+ status_code: 200
+ register: idrac_certificate_uri_data
+ when: idrac_ip is defined and idrac_password is defined
+ and idrac_user is defined
+ check_mode: false
+
+- name: Set firmware version
+ ansible.builtin.set_fact:
+ idrac_certificate_firmware_version: "{{ idrac_certificate_uri_data.json.FirmwareVersion }}"
+ when: idrac_certificate_uri_data.json is defined
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_helper.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_helper.yml
new file mode 100644
index 000000000..3994eed1e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_helper.yml
@@ -0,0 +1,40 @@
+---
+- name: Set the share vars
+ ansible.builtin.set_fact:
+ https_share_ip: "{{ lookup('env', 'https_share_ip') }}"
+ https_certificate_path: "{{ lookup('env', 'https_certificate_path') }}"
+ https_share_username: "{{ lookup('env', 'https_share_username') }}"
+ https_share_password: "{{ lookup('env', 'https_share_password') }}"
+ path_for_import_cert: "{{ lookup('env', 'path_for_import_cert') }}"
+ idrac_cert_dlg_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+ no_log: true
+
+- name: Create Directory
+ ansible.builtin.file:
+ path: "{{ path_for_import_cert }}"
+ state: directory
+ mode: "0755"
+ register: idrac_certificate_created_directory
+ check_mode: false
+ delegate_to: "{{ idrac_cert_dlg_to }}"
+
+- name: Setting up certificate path
+ ansible.builtin.stat:
+ path: "{{ path_for_import_cert }}"
+ register: idrac_certificate_check_file_created
+ check_mode: false
+ delegate_to: "{{ idrac_cert_dlg_to }}"
+
+- name: Copy file from HTTPS share to local machine
+ when: idrac_cert_name is defined and (idrac_cert_name | length > 0)
+ and idrac_certificate_check_file_created.stat.exists
+ ansible.builtin.uri:
+ url: "https://{{ https_share_ip }}{{ https_certificate_path }}{{ item }}"
+ dest: "{{ path_for_import_cert }}"
+ force_basic_auth: true
+ validate_certs: false
+ url_username: "{{ https_share_username }}"
+ url_password: "{{ https_share_password }}"
+ check_mode: false
+ loop: "{{ idrac_cert_name }}"
+ delegate_to: "{{ idrac_cert_dlg_to }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_ssl_key.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_ssl_key.yml
new file mode 100644
index 000000000..ed3c34000
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/__get_ssl_key.yml
@@ -0,0 +1,18 @@
+---
+- name: Create private key is present
+ community.crypto.openssl_privatekey:
+ path: "{{ lookup('env', 'path_for_import_cert') }}cert.key"
+ size: 2048
+ type: RSA
+ check_mode: false
+ no_log: true
+ delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+- name: Ensure self-signed cert is present
+ community.crypto.x509_certificate:
+ path: "{{ lookup('env', 'path_for_import_cert') }}cert.pem"
+ privatekey_path: "{{ lookup('env', 'path_for_import_cert') }}cert.key"
+ provider: selfsigned
+ check_mode: false
+ no_log: true
+ delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/converge.yml
new file mode 100644
index 000000000..56c26b4a6
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/converge.yml
@@ -0,0 +1,381 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ cert_export_path: "{{ lookup('env', 'certificate_path') }}"
+ import_cert_path: "{{ lookup('env', 'path_for_import_cert') }}"
+ custom_cert_name: "{{ lookup('env', 'custom_cert_name') }}"
+ cust_crt_name_pass: "{{ lookup('env', 'custom_cert_name_pass') }}"
+ csc_pass_cert: "{{ lookup('env', 'csc_passphrase_certificate') }}"
+ cert_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Invalid Scenarios
+ when: not ansible_check_mode
+ block:
+ - name: Set the failure messages
+ ansible.builtin.set_fact:
+ ssl_key_fail_msg: "Unable to locate the SSL key file"
+ ctc_invalid_path: "[Errno 2] No such file or directory"
+
+ - name: Create directory and fetch certificates
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ idrac_cert_name:
+ - "{{ custom_cert_name }}"
+ - "{{ cust_crt_name_pass }}"
+ - "{{ csc_pass_cert }}"
+
+ - name: Create SSL Key ans self-signed certificate
+ when: idrac_certificate_check_file_created is defined and
+ idrac_certificate_check_file_created.stat.exists
+ ansible.builtin.include_tasks:
+ file: ../__get_ssl_key.yml
+
+ - name: Export a Client Trust Certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "export"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "{{ cert_export_path }}"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ ignore_errors: true
+ register: idrac_certificate_res
+
+ - name: Setting up Client Trust certificate path for exported file
+ when: idrac_certificate_out.certificate_path is defined
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: ctc_cert_file
+ no_log: true
+
+ - name: Import a Client Trust Certificate invalid path
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "/path/invalid-path/to/certificate.pem"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ ignore_errors: true
+ register: idrrac_certificate_res_err
+
+ - name: Verifying Import a Client Trust Certificate invalid path
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - "ctc_invalid_path in idrac_certificate_out.msg"
+
+ - name: Import a Client Trust Certificate invalid certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "{{ lookup('env', 'invalid_certificate') }}"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ ignore_errors: true
+ register: idrac_certificate_res_err1
+
+ - name: Verifying Import a Client Trust Certificate invalid certificate
+ ansible.builtin.assert:
+ that:
+ - ('"HTTP Error 400" in idrac_certificate_out.msg')
+ - idrac_certificate_out.failed
+
+ - name: Import a Client Trust Certificate invalid certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "{{ lookup('env', 'invalid_certificate') }}"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ ignore_errors: true
+ register: idrac_certificate_res_err2
+
+ - name: Verifying Import a Client Trust Certificate invalid certificate
+ ansible.builtin.assert:
+ that:
+ - ('"HTTP Error 400" in idrac_certificate_out.msg')
+ - idrac_certificate_out.failed
+
+ - name: Import a Client Trust Certificate with invalid credentials
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'invalid_password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "import"
+ certificate_type: "CLIENT_TRUST_CERTIFICATE"
+ certificate_path: "{{ ctc_cert_file.stat.path }}"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ ignore_errors: true
+ register: res_err3
+
+ - name: Verifying Import a Client Trust Certificate
+ with invalid credentials
+ ansible.builtin.assert:
+ that:
+ - ('"HTTP Error 401" in idrac_certificate_out.msg')
+ - idrac_certificate_out.failed
+ when: idrac_certificate_out is defined
+
+ - name: Negative - unreachable host
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "999.999.999.999"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "reset"
+ certificate_type: "HTTPS"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_unreachable
+ ignore_errors: true
+ ignore_unreachable: true
+
+ - name: Verify task status - Negative - invalid unreachable host
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.unreachable
+ - '"Unable to communicate with" in idrac_certificate_out.msg'
+
+ - name: Negative - invalid idrac user
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: invalid
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "reset"
+ certificate_type: "HTTPS"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_idrac_user
+ ignore_errors: true
+
+ - name: Verify task status - Negative - invalid idrac user
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - '"HTTP Error 401: Unauthorized" in idrac_certificate_out.msg'
+
+ - name: Negative - invalid idrac password
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: invalid
+ validate_certs: false
+ command: "reset"
+ certificate_type: "HTTPS"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_idrac_pass
+ ignore_errors: true
+
+ - name: Verify task status - Negative - invalid idrac password
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - '"HTTP Error 401: Unauthorized" in idrac_certificate_out.msg'
+
+ - name: Invalid command
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "invalid"
+ certificate_type: "HTTPS"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_command
+ ignore_errors: true
+
+ - name: Verify task status - Negative - invalid command
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - not idrac_certificate_out.changed
+
+ - name: Invalid certificate path
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "export"
+ certificate_type: "HTTPS"
+ certificate_path: "invalid_dir"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_cert_path
+ ignore_errors: true
+
+ - name: Verify task status - Negative - invalid certificate path
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - not idrac_certificate_out.changed
+ - "'Provided directory path \\'invalid_dir\\' is
+ not valid.' == idrac_certificate_out.msg"
+
+ - name: Invalid passphrase
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "import"
+ certificate_type: "CSC"
+ certificate_path: "{{ import_cert_path }}{{ csc_pass_cert }}"
+ passphrase: "invalid"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_passphrase
+ ignore_errors: true
+
+ - name: Verify task status - Negative - invalid passphrase
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - not idrac_certificate_out.changed
+ - "'HTTP Error 400: Bad Request' == idrac_certificate_out.msg"
+
+ - name: Invalid certificate parameters to generate signing request
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "generate_csr"
+ certificate_type: "HTTPS"
+ certificate_path: "/root/"
+ cert_params:
+ invalid_args: "invalid"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_cert_params
+ ignore_errors: true
+
+ - name: Verify task status - Negative -
+ Invalid certificate parameters to generate signing request
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - not idrac_certificate_out.changed
+ - "'missing required arguments: common_name, country_code,
+ locality_name, organization_name, organization_unit,
+ state_name found in cert_params' == idrac_certificate_out.msg"
+
+ - name: Invalid passphrase for a valid custom
+ certificate without passphrase
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "import"
+ certificate_type: "CUSTOMCERTIFICATE"
+ certificate_path: "{{ import_cert_path }}{{ custom_cert_name }}"
+ passphrase: "invalid"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_custom_cert_pass
+ ignore_errors: true
+
+ - name: Verify task status
+ - Negative - invalid custom certificate passphrase
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - not idrac_certificate_out.changed
+ - "'HTTP Error 400: Bad Request' == idrac_certificate_out.msg"
+
+ - name: Invalid custom certificate
+ passphrase for a valid custom certificate
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "import"
+ certificate_type: "CUSTOMCERTIFICATE"
+ certificate_path: "{{ import_cert_path }}/{{ cust_crt_name_pass }}"
+ passphrase: "invalid"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_custom_cert_without_pass
+ ignore_errors: true
+
+ - name: Verify task status - Negative - invalid custom certificate
+ passphrase for a valid custom certificate
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - not idrac_certificate_out.changed
+ - "'HTTP Error 400: Bad Request' == idrac_certificate_out.msg"
+
+ - name: Invalid ssl key
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ command: "import"
+ certificate_type: "HTTPS"
+ certificate_path: "{{ import_cert_path }}cert.pem"
+ ssl_key: "invalid"
+ idrac_certificate_delegate: "{{ cert_delegate_to }}"
+ register: invalid_ssl_key
+ ignore_errors: true
+
+ - name: Verify task status - Negative - invalid ssl key
+ ansible.builtin.assert:
+ that:
+ - idrac_certificate_out.failed
+ - not idrac_certificate_out.changed
+ - "ssl_key_fail_msg in idrac_certificate_out.msg"
+
+ always:
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/default/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/converge.yml
new file mode 100644
index 000000000..9f57c7e84
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/converge.yml
@@ -0,0 +1,56 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+ cert_export_path: "{{ lookup('env', 'path_for_export_cert') }}"
+ idrac_delegate_to: "{{ lookup('env', 'idrac_certificate_delegate_to') }}"
+
+ tasks:
+ - name: Setting up directory
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+
+ - name: Generate HTTPS CSR signing request
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "generate_csr"
+ certificate_type: "HTTPS"
+ certificate_path: "{{ cert_export_path }}"
+ cert_params:
+ common_name: "sample.domain.com"
+ organization_unit: "OrgUnit"
+ locality_name: "Bangalore"
+ state_name: "Karnataka"
+ country_code: "IN"
+ email_address: "admin@domain.com"
+ organization_name: "OrgName"
+ subject_alt_name:
+ - "hostname1.chassis.com"
+ idrac_certificate_delegate: "{{ idrac_delegate_to }}"
+
+ - name: Setting up HTTPS CSR certificate path for exported file
+ ansible.builtin.stat:
+ path: "{{ idrac_certificate_out.certificate_path }}"
+ register: csr_cert_file
+ delegate_to: "{{ idrac_delegate_to }}"
+ no_log: true
+
+ - name: Verifying HTTPS generate CSR certificate
+ ansible.builtin.assert:
+ that:
+ - csr_cert_file.stat.exists
+ - not idrac_certificate_out.changed
+ - not idrac_certificate_out.failed
+ - idrac_certificate_out.msg == "Successfully performed the 'generate_csr' certificate operation."
+
+ - name: Deleting the directory
+ ansible.builtin.include_tasks:
+ file: ../__delete_directory.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/generateCSR/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/converge.yml
new file mode 100644
index 000000000..8a3e23ab5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/converge.yml
@@ -0,0 +1,31 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ ca_cert_path: "{{ lookup('env', 'ca_cert_path') }}"
+
+ tasks:
+ - name: Reset HTTPS certificate
+ ansible.builtin.import_role:
+ name: idrac_certificate
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ca_path: "{{ ca_cert_path }}"
+ command: "reset"
+ certificate_type: "HTTPS"
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with Normal/Idempotence mode.
+ ansible.builtin.assert:
+ that: idrac_certificate_out.msg == "Successfully performed the
+ 'reset' certificate operation.iDRAC
+ has been reset successfully."
+ when: not ansible_check_mode and idrac_certificate_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/molecule/reset/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/export.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/export.yml
new file mode 100644
index 000000000..3f4044e31
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/export.yml
@@ -0,0 +1,14 @@
+- name: Exporting certificate.
+ dellemc.openmanage.idrac_certificates:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ timeout: "{{ https_timeout }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ command: "export"
+ certificate_type: "{{ certificate_type }}"
+ certificate_path: "{{ certificate_path }}"
+ register: idrac_certificate_out
+ delegate_to: "{{ idrac_certificate_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/generate_csr.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/generate_csr.yml
new file mode 100644
index 000000000..25a958fa2
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/generate_csr.yml
@@ -0,0 +1,24 @@
+---
+- name: Generate HTTPS certificate signing request
+ dellemc.openmanage.idrac_certificates:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ timeout: "{{ https_timeout }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ command: "generate_csr"
+ certificate_type: "{{ certificate_type }}"
+ certificate_path: "{{ certificate_path }}"
+ cert_params:
+ common_name: "{{ cert_params.common_name | default(omit) }}"
+ organization_unit: "{{ cert_params.organization_unit | default(omit) }}"
+ locality_name: "{{ cert_params.locality_name | default(omit) }}"
+ state_name: "{{ cert_params.state_name | default(omit) }}"
+ country_code: "{{ cert_params.country_code | default(omit) }}"
+ email_address: "{{ cert_params.email_address | default(omit) }}"
+ organization_name: "{{ cert_params.organization_name | default(omit) }}"
+ subject_alt_name: "{{ cert_params.subject_alt_name | default(omit) }}"
+ register: idrac_certificate_out
+ delegate_to: "{{ idrac_certificate_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/import.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/import.yml
new file mode 100644
index 000000000..eab08d4b7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/import.yml
@@ -0,0 +1,18 @@
+- name: Importing certificate.
+ dellemc.openmanage.idrac_certificates:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ timeout: "{{ https_timeout }}"
+ validate_certs: "{{ validate_certs }}"
+ passphrase: "{{ passphrase | default(omit) }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ command: "import"
+ certificate_type: "{{ certificate_type }}"
+ certificate_path: "{{ certificate_path }}"
+ ssl_key: "{{ ssl_key | default(omit) }}"
+ reset: "{{ reset }}"
+ wait: "{{ wait }}"
+ register: idrac_certificate_out
+ delegate_to: "{{ idrac_certificate_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/main.yml
new file mode 100644
index 000000000..1c586570b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/main.yml
@@ -0,0 +1,18 @@
+---
+# tasks file for idrac_certificate
+
+- name: Generate CSR
+ ansible.builtin.include_tasks: generate_csr.yml
+ when: command == "generate_csr"
+
+- name: Import certificate
+ ansible.builtin.include_tasks: import.yml
+ when: command == "import"
+
+- name: Export certificate
+ ansible.builtin.include_tasks: export.yml
+ when: command == "export"
+
+- name: Reset certificate
+ ansible.builtin.include_tasks: reset.yml
+ when: command == "reset"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/reset.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/reset.yml
new file mode 100644
index 000000000..dd8f01d1c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tasks/reset.yml
@@ -0,0 +1,16 @@
+---
+- name: Reset Certificate
+ dellemc.openmanage.idrac_certificates:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ timeout: "{{ https_timeout }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ command: "reset"
+ reset: "{{ reset }}"
+ wait: "{{ wait }}"
+ certificate_type: "HTTPS"
+ register: idrac_certificate_out
+ delegate_to: "{{ idrac_certificate_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/inventory
new file mode 100644
index 000000000..2fbb50c4a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/inventory
@@ -0,0 +1 @@
+localhost
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/test.yml
new file mode 100644
index 000000000..bdd3628e3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: This role is to generate certificate signing request, import, and export certificates on iDRAC.
+- hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_certificate
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_certificate/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/vars/main.yml
new file mode 100644
index 000000000..ea6e3efad
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_certificate/vars/main.yml
@@ -0,0 +1,3 @@
+---
+# vars file for idrac_certificate
+idrac_certificate_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/README.md
new file mode 100644
index 000000000..69b76936b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/README.md
@@ -0,0 +1,361 @@
+# idrac_export_server_config_profile
+
+Role to Export the Server Configuration Profile (SCP) from the iDRAC to a network share (CIFS, NFS, HTTP, HTTPS) or a local path.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>idrac_ip</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>idrac_user</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>idrac_password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>idrac_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>idrac_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>share_parameters</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>Network share parameters.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;share_name</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Network share or local path.<br>- CIFS, NFS, HTTP, and HTTPS network share types are supported.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scp_file</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Name of the server configuration profile (SCP) file.</br>- The default format `idrac_ip_YYMMDD_HHMMSS_scp` is used if this option is not specified.</br>- I(export_format) is used if the valid extension file is not provided.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;share_user</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Network share user in the format 'user@domain' or 'domain\\user' if user is part of a domain else 'user'. This option is mandatory for CIFS Network Share..</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;share_password</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Network share user password. This option is mandatory for CIFS Network Share.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_support</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Proxy to be enabled or disabled.</br>- I(proxy_support) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_type</td>
+ <td>false</td>
+ <td>http</td>
+ <td>http, socks4</td>
+ <td>str</td>
+ <td>- C(http) to select HTTP type proxy.</br>- C(socks4) to select SOCKS4 type proxy.</br>- I(proxy_type) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_server</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td> - I(proxy_server) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).</br>- I(proxy_server) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_port</td>
+ <td>false</td>
+ <td>80</td>
+ <td></td>
+ <td>str</td>
+ <td>- Proxy port to authenticate.</br> - I(proxy_port) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).</br>- I(proxy_port) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_username</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Proxy username to authenticate.</br>- I(proxy_username) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_password</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Proxy password to authenticate.</br>- I(proxy_password) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ignore_certificate_warning</td>
+ <td>false</td>
+ <td>ignore</td>
+ <td>ignore, showerror</td>
+ <td>str</td>
+ <td>- If C(ignore), it ignores the certificate warnings.</br>- If C(showerror), it shows the certificate warnings.</br>- I(ignore_certificate_warning) is considered only when I(share_name) is of type HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>include_in_export</td>
+ <td>false</td>
+ <td>default</td>
+ <td>default, readonly, passwordhashvalues, customtelemetry</td>
+ <td>str</td>
+ <td>- This option is applicable when I(command) is C(export).<br>- If C(default), it exports the default Server Configuration Profile.<br>- If C(readonly), it exports the SCP with readonly attributes.<br>- If C(passwordhashvalues), it exports the SCP with password hash values.<br>- If C(customtelemetry), exports the SCP with custom telemetry attributes supported only in the iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>target</td>
+ <td>false</td>
+ <td>['ALL']</td>
+ <td>'ALL', 'IDRAC', 'BIOS', 'NIC', 'RAID'</td>
+ <td>str</td>
+ <td>- If C(ALL), this module exports or imports all components configurations from SCP file.<br>- If C(IDRAC), this module exports or imports iDRAC configuration from SCP file.<br>- If C(BIOS), this module exports or imports BIOS configuration from SCP file.<br>- If C(NIC), this module exports or imports NIC configuration from SCP file.<br>- If C(RAID), this module exports or imports RAID configuration from SCP file.</br>- When I(command) is C(export) or C(import) I(target) with multiple components is supported only on iDRAC9 with firmware 6.10.00.00 and above.</td>
+ </tr>
+ <tr>
+ <td>export_format</td>
+ <td>false</td>
+ <td>'XML'</td>
+ <td>'JSON', 'XML'</td>
+ <td>str</td>
+ <td>- Specify the output file format. This option is applicable for C(export) command.</td>
+ </tr>
+ <tr>
+ <td>export_use</td>
+ <td>false</td>
+ <td>'Default'</td>
+ <td>'Default', 'Clone', 'Replace'</td>
+ <td></td>
+ <td>- Specify the type of Server Configuration Profile (SCP) to be exported.<br>- This option is applicable when I(command) is C(export).<br>- C(Default) Creates a non-destructive snapshot of the configuration.<br>- C(Replace) Replaces a server with another or restores the servers settings to a known baseline.<br>- C(Clone) Clones settings from one server to another server with the identical hardware setup.</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact varaibles
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>out_scp</td>
+ <td>{
+ "changed": false,
+ "failed": false,
+ "msg": "Successfully exported the Server Configuration Profile.",
+ "scp_status": {
+ "ActualRunningStartTime": "2023-02-21T10:59:50",
+ "ActualRunningStopTime": "2023-02-21T11:00:08",
+ "CompletionTime": "2023-02-21T11:00:08",
+ "Id": "JID_769771903262",
+ "JobState": "Completed",
+ "JobType": "ExportConfiguration",
+ "Message": "Successfully exported Server Configuration Profile",
+ "MessageArgs": [],
+ "MessageId": "SYS043",
+ "PercentComplete": 100,
+ "TargetSettingsURI": null,
+ "file": ".\\192.1.2.1_2023221_16301_scp.xml",
+ "retval": true
+ }
+ }</td>
+ <td>Module output of the Server Configuration Job</td>
+ </tr>
+ <tr>
+ <td>share_type</td>
+ <td>NFS</td>
+ <td>Stores the share type sent as part of the role variables</td>
+ </tr>
+ </tbody>
+</table>
+
+## Examples
+-----
+
+```
+- name: Exporting SCP local path with all components
+ ansible.builtin.import_role:
+ name: idrac_export_server_config_profile
+ vars:
+ idrac_ip: "192.1.2.1"
+ idrac_user: "username"
+ idrac_password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ share_parameters:
+ share_name: "/root/tmp"
+ scp_file: "file.xml"
+```
+```
+- name: "Exporting SCP to NFS with iDRAC components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "192.1.2.1"
+ idrac_user: "username"
+ idrac_password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['IDRAC']
+ share_parameters:
+ share_name: "191.2.1.1:/nfs"
+ scp_file: "file.json"
+```
+```
+- name: "Exporting SCP to CIFS with BIOS components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "192.1.2.1"
+ idrac_user: "username"
+ idrac_password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['BIOS']
+ share_parameters:
+ share_name: "\\\\191.1.1.1\\cifs"
+ share_user: "username"
+ share_password: "password"
+ scp_file: "file.xml"
+```
+```
+- name: "Exporting SCP to HTTPS with RAID components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "192.1.2.1"
+ idrac_user: "username"
+ idrac_password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['RAID']
+ share_parameters:
+ share_name: "https://192.1.1.1/share"
+ share_user: "username"
+ share_password: "password"
+ scp_file: "filename.json"
+```
+```
+- name: "Exporting SCP to HTTP with NIC components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "192.1.2.1"
+ idrac_user: "username"
+ idrac_password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['NIC']
+ share_parameters:
+ share_name: "http://192.1.1.1/share"
+ share_user: "username"
+ share_password: "password"
+ scp_file: "filename.xml"
+```
+```
+- name: Export SCP
+ hosts: idrac
+ roles:
+ - role: idrac_export_server_config_profile
+```
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Abhishek Sinha (Abhishek.Sinha10@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/defaults/main.yml
new file mode 100644
index 000000000..96b7d2127
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/defaults/main.yml
@@ -0,0 +1,15 @@
+---
+# defaults file for idrac_export_server_config_profile
+
+idrac_port: 443
+validate_certs: true
+idrac_timeout: 30
+share_parameters:
+ proxy_support: false
+ proxy_type: http
+ proxy_port: "80"
+ ignore_certificate_warning: ignore
+target: ['ALL']
+export_format: XML
+export_use: Default
+include_in_export: default
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/handlers/main.yml
new file mode 100644
index 000000000..f1a862b9a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_export_server_config_profile
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/argument_specs.yml
new file mode 100644
index 000000000..d9e222844
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/argument_specs.yml
@@ -0,0 +1,143 @@
+---
+argument_specs:
+ main:
+ version_added: "7.3.0"
+ short_description: Role to export iDRAC Server Configuration Profile (SCP)
+ description:
+ - Role to export the Server Configuration Profile (SCP) from the iDRAC to a network share (CIFS, NFS, HTTP, HTTPS) or a local path.
+ options:
+ idrac_ip:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ idrac_user:
+ type: str
+ description: iDRAC username.
+ idrac_password:
+ type: str
+ description: iDRAC user password.
+ idrac_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ idrac_timeout:
+ description: The HTTPS socket level timeout in seconds.
+ type: int
+ default: 30
+ share_parameters:
+ description: Network share parameters.
+ type: dict
+ options:
+ share_name:
+ required: true
+ description:
+ - Network share or local path.
+ - CIFS, NFS, HTTP, and HTTPS network share types are supported.
+ - I(share_name) is mutually exclusive with I(import_buffer).
+ type: str
+ scp_file:
+ description:
+ - Name of the server configuration profile (SCP) file.
+ - The default format <idrac_ip>_YYMMDD_HHMMSS_scp is used if this option is not specified.
+ - I(export_format) is used if the valid extension file is not provided.
+ type: str
+ share_user:
+ description:
+ Network share user in the format 'user@domain' or 'domain\\user' if user is
+ part of a domain else 'user'. This option is mandatory for CIFS Network Share.
+ type: str
+ share_password:
+ description: Network share user password. This option is mandatory for CIFS Network Share.
+ type: str
+ proxy_support:
+ description:
+ - Proxy to be enabled or disabled.
+ - I(proxy_support) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: bool
+ default: false
+ proxy_type:
+ description:
+ - C(http) to select HTTP type proxy.
+ - C(socks4) to select SOCKS4 type proxy.
+ - I(proxy_type) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ choices: [http, socks4]
+ default: http
+ proxy_server:
+ description:
+ - I(proxy_server) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).
+ - I(proxy_server) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ proxy_port:
+ description:
+ - Proxy port to authenticate.
+ - I(proxy_port) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).
+ - I(proxy_port) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ default: 80
+ proxy_username:
+ description:
+ - Proxy username to authenticate.
+ - I(proxy_username) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ proxy_password:
+ description:
+ - Proxy password to authenticate.
+ - I(proxy_password) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ ignore_certificate_warning:
+ description:
+ - If C(ignore), it ignores the certificate warnings.
+ - If C(showerror), it shows the certificate warnings.
+ - I(ignore_certificate_warning) is considered only when I(share_name) is of type HTTPS and is
+ supported only on iDRAC9.
+ type: str
+ choices: [ignore, showerror]
+ default: ignore
+ include_in_export:
+ description:
+ - This option is applicable when I(command) is C(export).
+ - If C(default), it exports the default Server Configuration Profile.
+ - If C(readonly), it exports the SCP with readonly attributes.
+ - If C(passwordhashvalues), it exports the SCP with password hash values.
+ - If C(customtelemetry), exports the SCP with custom telemetry attributes supported only in the iDRAC9.
+ type: str
+ choices: [default, readonly, passwordhashvalues, customtelemetry]
+ default: default
+ target:
+ description:
+ - If C(ALL), this module exports or imports all components configurations from SCP file.
+ - If C(IDRAC), this module exports or imports iDRAC configuration from SCP file.
+ - If C(BIOS), this module exports or imports BIOS configuration from SCP file.
+ - If C(NIC), this module exports or imports NIC configuration from SCP file.
+ - If C(RAID), this module exports or imports RAID configuration from SCP file.
+ choices: ["ALL", "IDRAC", "BIOS", "NIC", "RAID"]
+ default: ["ALL"]
+ type: list
+ export_format:
+ description: Specify the output file format. This option is applicable for C(export) command.
+ type: str
+ choices: ["JSON", "XML"]
+ default: "XML"
+ export_use:
+ description:
+ - Specify the type of Server Configuration Profile (SCP) to be exported.
+ - This option is applicable when I(command) is C(export).
+ - C(Default) Creates a non-destructive snapshot of the configuration.
+ - C(Replace) Replaces a server with another or restores the servers settings to a known baseline.
+ - C(Clone) Clones settings from one server to another server with the identical hardware setup.
+ All settings except I/O identity are updated (e.g. will reset RAID). The settings in this export
+ will be destructive when uploaded to another system.
+ type: str
+ choices: ["Default", "Clone", "Replace"]
+ default: "Default"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/main.yml
new file mode 100644
index 000000000..6c63527fe
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/meta/main.yml
@@ -0,0 +1,53 @@
+galaxy_info:
+ author: 'Abhishek-Dell'
+ description: The role performs Export operation of Server Configuration Profile.
+ company: Dell Technologies
+
+ # 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.13"
+
+ # If this a Container Enabled role, provide the minimum Ansible Container version.
+ # min_ansible_container_version:
+
+ #
+ # Provide a list of supported platforms, and for each platform a list of versions.
+ # If you don't wish to enumerate all versions for a particular platform, use 'all'.
+ # To view available platforms and versions (or releases), visit:
+ # https://galaxy.ansible.com/api/v1/platforms/
+ #
+ 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.
+
+dependencies: []
+ # List your role dependencies here, one per line. Be sure to remove the '[]' above,
+ # if you add dependencies to this list.
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/cleanup.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/cleanup.yml
new file mode 100644
index 000000000..9ade81e90
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/cleanup.yml
@@ -0,0 +1,96 @@
+---
+# This is an example playbook to execute Ansible cleanup.
+
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ vars:
+ local_path: "{{ lookup('env', 'local_path') }}"
+ local_filename: "{{ lookup('env', 'local_filename') }}"
+ nfs_filename: "{{ lookup('env', 'nfs_filename') }}"
+ cifs_filename: "{{ lookup('env', 'cifs_filename') }}"
+ https_filename: "{{ lookup('env', 'https_filename') }}"
+ http_filename: "{{ lookup('env', 'http_filename') }}"
+ nfs_mount_path: "{{ lookup('env', 'nfs_mount_path') }}"
+ cifs_mount_path: "{{ lookup('env', 'cifs_mount_path') }}"
+
+ nfs_url: "{{ lookup('env', 'NFS_URL') }}"
+ cifs_url: "{{ lookup('env', 'CIFS_URL') }}"
+ cifs_username: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ cifs_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+
+ https_url: "{{ lookup('env', 'HTTPS_URL') }}"
+ https_username: "{{ lookup('env', 'HTTPS_USERNAME') }}"
+ https_password: "{{ lookup('env', 'HTTPS_PASSWORD') }}"
+
+ http_url: "{{ lookup('env', 'HTTP_URL') }}"
+ http_username: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ http_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ tasks:
+ - name: Checking file exists in NFS mount localhost
+ ansible.builtin.stat:
+ path: "{{ nfs_mount_path }}/{{ nfs_filename }}"
+ delegate_to: localhost
+ register: nfs_file
+
+ - name: Checking file exists in CIFS mount localhost
+ ansible.builtin.stat:
+ path: "{{ cifs_mount_path }}/{{ cifs_filename }}"
+ delegate_to: localhost
+ register: cifs_file
+
+ - name: Checking file exists in current location
+ ansible.builtin.stat:
+ path: "{{ http_filename }}"
+ delegate_to: localhost
+ register: http_file
+
+ - name: Checking file exists in current location
+ ansible.builtin.stat:
+ path: "{{ https_filename }}"
+ delegate_to: localhost
+ register: https_file
+
+ - name: Deleting the file if exists in NFS mounted localhost
+ ansible.builtin.file:
+ path: "{{ nfs_mount_path }}/{{ nfs_filename }}"
+ state: absent
+ delegate_to: localhost
+ when: nfs_file.stat.exists
+
+ - name: Deleting the file if exists in CIFS mounted localhost
+ ansible.builtin.file:
+ path: "{{ cifs_mount_path }}/{{ cifs_filename }}"
+ state: absent
+ delegate_to: localhost
+ when: cifs_file.stat.exists
+
+ - name: Deleting the file if exists in HTTP localhost
+ ansible.builtin.file:
+ path: "{{ http_filename }}"
+ state: absent
+ delegate_to: localhost
+ when: http_file.stat.exists
+
+ - name: Deleting the file if exists in HTTPS localhost
+ ansible.builtin.file:
+ path: "{{ https_filename }}"
+ state: absent
+ delegate_to: localhost
+ when: https_file.stat.exists
+
+ - name: Unmounting NFS volume from localhost
+ ansible.posix.mount:
+ src: "{{ nfs_url }}"
+ path: "{{ nfs_mount_path }}"
+ state: unmounted
+ fstype: nfs
+ delegate_to: localhost
+
+ - name: Unmounting CIFS volume from localhost
+ ansible.posix.mount:
+ src: "{{ cifs_url }}"
+ path: "{{ cifs_mount_path }}"
+ state: unmounted
+ fstype: nfs
+ delegate_to: localhost
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/converge.yml
new file mode 100644
index 000000000..8073a85bc
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/converge.yml
@@ -0,0 +1,100 @@
+- name: Converge
+ hosts: all
+ vars:
+ local_path: "{{ lookup('env', 'local_path') }}"
+ local_filename: "{{ lookup('env', 'local_filename') }}"
+ nfs_filename: "{{ lookup('env', 'nfs_filename') }}"
+ cifs_filename: "{{ lookup('env', 'cifs_filename') }}"
+ https_filename: "{{ lookup('env', 'https_filename') }}"
+ http_filename: "{{ lookup('env', 'http_filename') }}"
+ nfs_mount_path: "{{ lookup('env', 'nfs_mount_path') }}"
+ cifs_mount_path: "{{ lookup('env', 'nfs_mount_path') }}"
+
+ nfs_url: "{{ lookup('env', 'NFS_URL') }}"
+ cifs_url: "{{ lookup('env', 'CIFS_URL') }}"
+ cifs_username: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ cifs_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+
+ https_url: "{{ lookup('env', 'HTTPS_URL') }}"
+ https_username: "{{ lookup('env', 'HTTPS_USERNAME') }}"
+ https_password: "{{ lookup('env', 'HTTPS_PASSWORD') }}"
+
+ http_url: "{{ lookup('env', 'HTTP_URL') }}"
+ http_username: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ http_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ gather_facts: false
+ tasks:
+ - name: Exporting SCP local path with all components
+ ansible.builtin.import_role:
+ name: idrac_export_server_config_profile
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USER') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ job_wait: true
+ share_parameters:
+ share_name: "{{ local_path }}"
+ scp_file: "{{ local_filename }}"
+
+ - name: "Exporting SCP to NFS with iDRAC components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USER') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ target: ['IDRAC']
+ job_wait: true
+ share_parameters:
+ share_name: "{{ nfs_url }}"
+ scp_file: "{{ nfs_filename }}"
+
+ - name: "Exporting SCP to CIFS with BIOS components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USER') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ target: ['BIOS']
+ job_wait: true
+ share_parameters:
+ share_name: "{{ cifs_url }}"
+ share_user: "{{ cifs_username }}"
+ share_password: "{{ cifs_password }}"
+ scp_file: "{{ cifs_filename }}"
+
+ - name: "Exporting SCP to HTTPS with RAID components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USER') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ target: ['RAID']
+ job_wait: true
+ share_parameters:
+ share_name: "{{ https_url }}"
+ share_user: "{{ https_username }}"
+ share_password: "{{ https_password }}"
+ scp_file: "{{ https_filename }}"
+
+ - name: "Exporting SCP to HTTP with NIC components"
+ ansible.builtin.import_role:
+ name: "idrac_export_server_config_profile"
+ vars:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USER') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ target: ['NIC']
+ job_wait: true
+ share_parameters:
+ share_name: "{{ http_url }}"
+ share_user: "{{ http_username }}"
+ share_password: "{{ http_password }}"
+ scp_file: "{{ http_filename }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/molecule.yml
new file mode 100644
index 000000000..c2dae4dce
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/molecule.yml
@@ -0,0 +1,12 @@
+---
+provisioner:
+ name: ansible
+ env:
+ local_path: "/tmp"
+ local_filename: "exported_scp_local.xml"
+ nfs_filename: "exported_scp_nfs.json"
+ cifs_filename: 'exported_scp_cifs.xml'
+ https_filename: "exported_scp_https.json"
+ http_filename: "exported_scp_http.xml"
+ nfs_mount_path: "/tmp/nfs"
+ cifs_mount_path: "/tmp/cifs"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/verify.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/verify.yml
new file mode 100644
index 000000000..25206e2d3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/molecule/default/verify.yml
@@ -0,0 +1,115 @@
+---
+# This is an example playbook to execute Ansible tests.
+
+- name: Verify
+ hosts: all
+ gather_facts: false
+ vars:
+ local_path: "{{ lookup('env', 'local_path') }}"
+ local_filename: "{{ lookup('env', 'local_filename') }}"
+ nfs_filename: "{{ lookup('env', 'nfs_filename') }}"
+ cifs_filename: "{{ lookup('env', 'cifs_filename') }}"
+ https_filename: "{{ lookup('env', 'https_filename') }}"
+ http_filename: "{{ lookup('env', 'http_filename') }}"
+ nfs_mount_path: "{{ lookup('env', 'nfs_mount_path') }}"
+ cifs_mount_path: "{{ lookup('env', 'cifs_mount_path') }}"
+
+ nfs_url: "{{ lookup('env', 'NFS_URL') }}"
+ cifs_url: "{{ lookup('env', 'CIFS_URL') }}"
+ cifs_username: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ cifs_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+
+ https_url: "{{ lookup('env', 'HTTPS_URL') }}"
+ https_username: "{{ lookup('env', 'HTTPS_USERNAME') }}"
+ https_password: "{{ lookup('env', 'HTTPS_PASSWORD') }}"
+
+ http_url: "{{ lookup('env', 'HTTP_URL') }}"
+ http_username: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ http_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ tasks:
+ - name: Checking exported file exists in Local path
+ ansible.builtin.stat:
+ path: "{{ local_path }}/{{ local_filename }}"
+ delegate_to: localhost
+ register: local_file
+
+ - name: Mounting NFS volume to localhost
+ ansible.posix.mount:
+ src: "{{ nfs_url }}"
+ path: "{{ nfs_mount_path }}"
+ state: mounted
+ fstype: nfs
+ delegate_to: localhost
+ register: nfs_mount
+
+ - name: Checking file exists in NFS mount localhost
+ ansible.builtin.stat:
+ path: "{{ nfs_mount_path }}/{{ nfs_filename }}"
+ delegate_to: localhost
+ register: nfs_file
+
+ - name: Mounting CIFS volume to localhost
+ ansible.posix.mount:
+ src: "{{ cifs_url }}"
+ path: "{{ cifs_mount_path }}"
+ opts: "username={{ cifs_username }},password={{ cifs_password }}"
+ state: mounted
+ fstype: cifs
+ delegate_to: localhost
+ register: cifs_mount
+ no_log: true
+
+ - name: Checking file exists in CIFS mount localhost
+ ansible.builtin.stat:
+ path: "{{ cifs_mount_path }}/{{ cifs_filename }}"
+ delegate_to: localhost
+ register: cifs_file
+
+ - name: Downloading HTTP file to localhost
+ ansible.builtin.uri:
+ url: "{{ http_url }}/{{ http_filename }}"
+ dest: .
+ force_basic_auth: true
+ validate_certs: false
+ url_username: "{{ http_username }}"
+ url_password: "{{ http_password }}"
+ mode: '0755'
+ delegate_to: localhost
+ register: http_file_download
+ no_log: true
+ changed_when: false
+
+ - name: Checking file exists in current location
+ ansible.builtin.stat:
+ path: "{{ http_filename }}"
+ delegate_to: localhost
+ register: http_file
+
+ - name: Downloading HTTPS file to localhost
+ ansible.builtin.uri:
+ url: "{{ https_url }}/{{ https_filename }}"
+ dest: .
+ force_basic_auth: true
+ validate_certs: false
+ url_username: "{{ https_username }}"
+ url_password: "{{ https_password }}"
+ mode: '0755'
+ delegate_to: localhost
+ register: https_file_download
+ no_log: true
+ changed_when: false
+
+ - name: Checking file exists in current location
+ ansible.builtin.stat:
+ path: "{{ https_filename }}"
+ delegate_to: localhost
+ register: https_file
+
+ - name: Verifying file exists
+ ansible.builtin.assert:
+ that:
+ - local_file.stat.exists
+ - nfs_file.stat.exists
+ - cifs_file.stat.exists
+ - http_file.stat.exists
+ - https_file.stat.exists
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/main.yml
new file mode 100644
index 000000000..2b19130c5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/main.yml
@@ -0,0 +1,24 @@
+---
+# tasks file for idrac_export_server_config_profile
+- name: Pre-req
+ ansible.builtin.include_tasks: pre_req.yml
+
+- name: Local path
+ ansible.builtin.include_tasks: scp_export_local.yml
+ when: share_type == 'Local'
+
+- name: NFS
+ ansible.builtin.include_tasks: scp_export_nfs.yml
+ when: share_type == 'NFS'
+
+- name: CIFS
+ ansible.builtin.include_tasks: scp_export_cifs.yml
+ when: share_type == 'CIFS'
+
+- name: HTTP
+ ansible.builtin.include_tasks: scp_export_http.yml
+ when: share_type == 'HTTP'
+
+- name: HTTPS
+ ansible.builtin.include_tasks: scp_export_https.yml
+ when: share_type == 'HTTPS'
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/pre_req.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/pre_req.yml
new file mode 100644
index 000000000..9668f7ee1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/pre_req.yml
@@ -0,0 +1,13 @@
+- name: Initializing share_type
+ ansible.builtin.set_fact:
+ share_type: ''
+
+- name: Checking network share type is CIFS, HTTPS, HTTP
+ ansible.builtin.set_fact:
+ share_type: "{{ item.key if share_parameters.share_name.startswith(item.value) else share_type }}"
+ with_dict: { 'HTTPS': 'https://', 'HTTP': 'http://', 'CIFS': '\\'}
+
+- name: Checking network share type is NFS, Local
+ ansible.builtin.set_fact:
+ share_type: "{{ 'NFS' if ':' in share_parameters.share_name else 'Local' }}"
+ when: share_type == ''
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_cifs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_cifs.yml
new file mode 100644
index 000000000..5fd79dcbb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_cifs.yml
@@ -0,0 +1,21 @@
+---
+- name: Exporting the SCP components to CIFS
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ idrac_ip }}"
+ idrac_port: "{{ idrac_port }}"
+ idrac_user: "{{ idrac_user }}"
+ idrac_password: "{{ idrac_password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ idrac_timeout }}"
+ export_format: "{{ export_format }}"
+ export_use: "{{ export_use }}"
+ include_in_export: "{{ include_in_export }}"
+ share_user: "{{ share_parameters.share_user | default(omit) }}"
+ share_password: "{{ share_parameters.share_password | default(omit) }}"
+ share_name: "{{ share_parameters.share_name }}"
+ scp_file: "{{ share_parameters.scp_file | default(omit) }}"
+ target: "{{ target }}"
+ job_wait: "{{ idrac_export_server_config_profile_job_wait }}"
+ register: out_scp
+ delegate_to: "{{ idrac_export_server_config_profile_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_http.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_http.yml
new file mode 100644
index 000000000..abb85c268
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_http.yml
@@ -0,0 +1,27 @@
+---
+- name: Exporting the SCP components to HTTP
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ idrac_ip }}"
+ idrac_port: "{{ idrac_port }}"
+ idrac_user: "{{ idrac_user }}"
+ idrac_password: "{{ idrac_password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ idrac_timeout }}"
+ export_format: "{{ export_format }}"
+ export_use: "{{ export_use }}"
+ include_in_export: "{{ include_in_export }}"
+ share_user: "{{ share_parameters.share_user | default(omit) }}"
+ share_password: "{{ share_parameters.share_password | default(omit) }}"
+ share_name: "{{ share_parameters.share_name }}"
+ scp_file: "{{ share_parameters.scp_file | default(omit) }}"
+ target: "{{ target }}"
+ proxy_support: "{{ share_parameters.proxy_support | default(omit) }}"
+ proxy_type: "{{ share_parameters.proxy_type | default(omit) }}"
+ proxy_server: "{{ share_parameters.proxy_server | default(omit) }}"
+ proxy_port: "{{ share_parameters.proxy_port | default(omit) }}"
+ proxy_username: "{{ share_parameters.proxy_username | default(omit) }}"
+ proxy_password: "{{ share_parameters.proxy_password | default(omit) }}"
+ job_wait: "{{ idrac_export_server_config_profile_job_wait }}"
+ register: out_scp
+ delegate_to: "{{ idrac_export_server_config_profile_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_https.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_https.yml
new file mode 100644
index 000000000..233a5083d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_https.yml
@@ -0,0 +1,28 @@
+---
+- name: Exporting the SCP components to HTTPS
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ idrac_ip }}"
+ idrac_port: "{{ idrac_port }}"
+ idrac_user: "{{ idrac_user }}"
+ idrac_password: "{{ idrac_password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ idrac_timeout }}"
+ export_format: "{{ export_format }}"
+ export_use: "{{ export_use }}"
+ include_in_export: "{{ include_in_export }}"
+ share_user: "{{ share_parameters.share_user | default(omit) }}"
+ share_password: "{{ share_parameters.share_password | default(omit) }}"
+ share_name: "{{ share_parameters.share_name }}"
+ scp_file: "{{ share_parameters.scp_file | default(omit) }}"
+ target: "{{ target }}"
+ proxy_support: "{{ share_parameters.proxy_support | default(omit) }}"
+ proxy_type: "{{ share_parameters.proxy_type | default(omit) }}"
+ proxy_server: "{{ share_parameters.proxy_server | default(omit) }}"
+ proxy_port: "{{ share_parameters.proxy_port | default(omit) }}"
+ proxy_username: "{{ share_parameters.proxy_username | default(omit) }}"
+ proxy_password: "{{ share_parameters.proxy_password | default(omit) }}"
+ ignore_certificate_warning: "{{ share_parameters.ignore_certificate_warning | default(omit) }}"
+ job_wait: "{{ idrac_export_server_config_profile_job_wait }}"
+ register: out_scp
+ delegate_to: "{{ idrac_export_server_config_profile_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_local.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_local.yml
new file mode 100644
index 000000000..a6da9df20
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_local.yml
@@ -0,0 +1,19 @@
+---
+- name: Exporting the SCP components to local
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ idrac_ip }}"
+ idrac_port: "{{ idrac_port }}"
+ idrac_user: "{{ idrac_user }}"
+ idrac_password: "{{ idrac_password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ idrac_timeout }}"
+ export_format: "{{ export_format }}"
+ export_use: "{{ export_use }}"
+ include_in_export: "{{ include_in_export }}"
+ share_name: "{{ share_parameters.share_name }}"
+ target: "{{ target }}"
+ scp_file: "{{ share_parameters.scp_file | default(omit) }}"
+ job_wait: "{{ idrac_export_server_config_profile_job_wait }}"
+ register: out_scp
+ delegate_to: "{{ idrac_export_server_config_profile_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_nfs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_nfs.yml
new file mode 100644
index 000000000..355da446f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tasks/scp_export_nfs.yml
@@ -0,0 +1,19 @@
+---
+- name: Exporting the SCP components to NFS
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ idrac_ip }}"
+ idrac_port: "{{ idrac_port }}"
+ idrac_user: "{{ idrac_user }}"
+ idrac_password: "{{ idrac_password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ idrac_timeout }}"
+ export_format: "{{ export_format }}"
+ export_use: "{{ export_use }}"
+ include_in_export: "{{ include_in_export }}"
+ share_name: "{{ share_parameters.share_name }}"
+ target: "{{ target }}"
+ scp_file: "{{ share_parameters.scp_file | default(omit) }}"
+ job_wait: "{{ idrac_export_server_config_profile_job_wait }}"
+ register: out_scp
+ delegate_to: "{{ idrac_export_server_config_profile_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/test.yml
new file mode 100644
index 000000000..313357676
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Exporitng idrac server config profile for iDRAC
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_export_server_config_profile
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/vars/main.yml
new file mode 100644
index 000000000..af054eb79
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_export_server_config_profile/vars/main.yml
@@ -0,0 +1,4 @@
+---
+# vars file for idrac_export_server_config_profile
+idrac_export_server_config_profile_job_wait: true
+idrac_export_server_config_profile_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/README.md
new file mode 100644
index 000000000..6b4dace7a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/README.md
@@ -0,0 +1,342 @@
+# idrac_firmware
+
+Update the Firmware by connecting to a network share (CIFS, NFS, HTTP, HTTPS, FTP) that contains a catalog of available updates.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+omsdk
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+omsdk
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>share_name</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Network share path of update repository. CIFS, NFS, HTTP, HTTPS and FTP share types are supported.</td>
+ </tr>
+ <tr>
+ <td>share_user</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Network share user in the format 'user@domain' or 'domain\\user' if user is part of a domain else 'user'. This option is mandatory for CIFS Network Share.</td>
+ </tr>
+ <tr>
+ <td>share_password</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Network share user password. This option is mandatory for CIFS Network Share.</td>
+ </tr>
+ <tr>
+ <td>catalog_file_name</td>
+ <td>false</td>
+ <td>Catalog.xml</td>
+ <td></td>
+ <td>str</td>
+ <td>- Catalog file name relative to the I(share_name</td>
+ </tr>
+ <tr>
+ <td>ignore_cert_warning</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Specifies if certificate warnings are ignored when HTTPS share is used.</br>- If C(true) option is set, then the certificate warnings are ignored.</td>
+ </tr>
+ <tr>
+ <td>apply_update</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td> - If I(apply_update) is set to C(true), then the packages are applied.</br>- If I(apply_update) is set to C(false), no updates are applied, and a catalog report of packages is generated and returned.</td>
+ </tr>
+ <tr>
+ <td>reboot</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Provides the option to apply the update packages immediately or in the next reboot.</br> - If I(reboot) is set to C(true), then the packages are applied immediately.</br>- If I(reboot) is set to C(false), then the packages are staged and applied in the next reboot.</br>- Packages that do not require a reboot are applied immediately irrespective of I (reboot).
+ </td>
+ </tr>
+ <tr>
+ <td>proxy_support</td>
+ <td>false</td>
+ <td>Off</td>
+ <td>"ParametersProxy", "DefaultProxy", "Off"</td>
+ <td>str</td>
+ <td>- Specifies if a proxy should be used.</br>- Proxy parameters are applicable on C(HTTP), C(HTTPS), and C(FTP) share type of repositories.</br> - C(ParametersProxy), sets the proxy parameters for the current firmware operation.</br>- C(DefaultProxy), iDRAC uses the proxy values set by default.</br>- Default Proxy can be set in the Lifecycle Controller attributes using M(dellemc.openmanage.idrac_attributes).</br>- C(Off), will not use the proxy.</br>- For iDRAC8 based servers, use proxy server with basic authentication.</br>- For iDRAC9 based servers, ensure that you use digest authentication for the proxy server, basic authentication is not supported.
+ </td>
+ </tr>
+ <tr>
+ <td>proxy_server</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The IP address of the proxy server.</br>- This IP will not be validated. The download job will be created even for invalid I(proxy_server).</br>- Please check the results of the job for error details.</br>- This is required when I(proxy_support) is C(ParametersProxy). </td>
+ </tr>
+ <tr>
+ <td>proxy_port</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>int</td>
+ <td>- The Port for the proxy server.</br>- This is required when I(proxy_support) is C(ParametersProxy).</td>
+ </tr>
+ <tr>
+ <td>proxy_type</td>
+ <td>false</td>
+ <td></td>
+ <td>HTTP, SOCKS</td>
+ <td>str</td>
+ <td>- The proxy type of the proxy server.</br>- This is required when I(proxy_support) is C(ParametersProxy).</td>
+ </tr>
+ <tr>
+ <td>proxy_uname</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The user name for the proxy server.</td>
+ </tr>
+ <tr>
+ <td>proxy_passwd</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The password for the proxy server.</td>
+ </tr>
+ <tr>
+ <td>job_wait</td>
+ <td>false</td>
+ <td></td>
+ <td>true</td>
+ <td>bool</td>
+ <td>- Whether to wait for job completion or not.</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_firmware_out</td>
+ <td>{
+msg: "Successfully updated the firmware."
+update_status: {
+ 'InstanceID': 'JID_XXXXXXXXXXXX',
+ 'JobState': 'Completed',
+ 'Message': 'Job completed successfully.',
+ 'MessageId': 'REDXXX',
+ 'Name': 'Repository Update',
+ 'JobStartTime': 'NA',
+ 'Status': 'Success',
+ }
+}</td>
+<td>Returns the output of the firmware update status</td>
+</tbody>
+</table>
+
+## Examples
+-----
+
+```yml
+- name: Update firmware from repository on a NFS Share
+ ansible.builtin.include_role:
+ name: idrac_firmware
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ share_name: "192.168.0.0:/share"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+
+```
+```yml
+- name: Update firmware from repository on a CIFS Share
+ ansible.builtin.ansible.builtin.include_role:
+ name: idrac_firmware
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ share_name: "full_cifs_path"
+ share_user: "share_user"
+ share_password: "share_password"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+```
+```yml
+- name: Update firmware from repository on a HTTP
+ ansible.builtin.include_role:
+ name: idrac_firmware
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ share_name: "http://downloads.dell.com"
+ reboot: true
+ job_wait: true
+ apply_update: true
+```
+```yml
+- name: Update firmware from repository on a HTTPS
+ ansible.builtin.include_role:
+ name: idrac_firmware
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ share_name: "https://downloads.dell.com"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ ```
+ ```yml
+- name: Update firmware from repository on a HTTPS via proxy
+ ansible.builtin.include_role:
+ name: idrac_firmware
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ share_name: "https://downloads.dell.com"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ proxy_support: ParametersProxy
+ proxy_server: 192.168.1.10
+ proxy_type: HTTP
+ proxy_port: 80
+ proxy_uname: "proxy_user"
+ proxy_passwd: "proxy_pwd"
+ ```
+ ```yml
+- name: Update firmware from repository on a FTP
+ ansible.builtin.include_role:
+ name: idrac_firmware
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ share_name: "ftp://ftp.mydomain.com"
+ reboot: true
+ job_wait: true
+ apply_update: true
+```
+## Author Information
+------------------
+
+Dell Technologies <br>
+Sachin Apagundi (Sachin.Apagundi@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/defaults/main.yml
new file mode 100644
index 000000000..a684e7406
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/defaults/main.yml
@@ -0,0 +1,11 @@
+---
+# defaults file for idrac_firmware
+https_port: 443
+validate_certs: true
+https_timeout: 30
+apply_update: true
+reboot: true
+proxy_support: "Off"
+job_wait: true
+ignore_cert_warning: true
+catalog_file_name: "Catalog.xml"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/handlers/main.yml
new file mode 100644
index 000000000..af82235fe
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_firmware
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/argument_specs.yml
new file mode 100644
index 000000000..b6ac77a86
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/argument_specs.yml
@@ -0,0 +1,114 @@
+---
+argument_specs:
+ main:
+ version_added: "7.5.0"
+ short_description: Firmware update from a repository on a network share (CIFS, NFS, HTTP, HTTPS, FTP)
+ description:
+ - Update the Firmware by connecting to a network share (CIFS, NFS, HTTP, HTTPS, FTP) that contains a catalog of available updates.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address or hostname.
+ username:
+ type: str
+ description: iDRAC username with admin privileges.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ http_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ share_name:
+ description: Network share path of update repository. CIFS, NFS, HTTP, HTTPS and FTP share types are supported.
+ type: str
+ required: true
+ share_user:
+ description:
+ Network share user in the format 'user@domain' or 'domain\\user' if user is
+ part of a domain else 'user'. This option is mandatory for CIFS Network Share.
+ type: str
+ share_password:
+ description: Network share user password. This option is mandatory for CIFS Network Share.
+ type: str
+ catalog_file_name:
+ description: Catalog file name relative to the I(share_name).
+ type: str
+ default: "Catalog.xml"
+ ignore_cert_warning:
+ description:
+ Specifies if certificate warnings are ignored when HTTPS share is used.
+ If C(true) option is set, then the certificate warnings are ignored.
+ type: bool
+ default: true
+ apply_update:
+ description:
+ - If I(apply_update) is set to C(true), then the packages are applied.
+ - If I(apply_update) is set to C(false), no updates are applied, and a catalog report
+ of packages is generated and returned.
+ type: bool
+ default: true
+ reboot:
+ description:
+ - Provides the option to apply the update packages immediately or in the next reboot.
+ - If I(reboot) is set to C(true), then the packages are applied immediately.
+ - If I(reboot) is set to C(false), then the packages are staged and applied in the next reboot.
+ - Packages that do not require a reboot are applied immediately irrespective of I (reboot).
+ type: bool
+ default: false
+ proxy_support:
+ description:
+ - Specifies if a proxy should be used.
+ - Proxy parameters are applicable on C(HTTP), C(HTTPS), and C(FTP) share type of repositories.
+ - C(ParametersProxy), sets the proxy parameters for the current firmware operation.
+ - C(DefaultProxy), iDRAC uses the proxy values set by default.
+ - Default Proxy can be set in the Lifecycle Controller attributes using M(dellemc.openmanage.idrac_attributes).
+ - C(Off), will not use the proxy.
+ - For iDRAC8 based servers, use proxy server with basic authentication.
+ - For iDRAC9 based servers, ensure that you use digest authentication for the proxy server, basic authentication is not supported.
+ choices: ["ParametersProxy", "DefaultProxy", "Off"]
+ type: str
+ default: "Off"
+ proxy_server:
+ description:
+ - The IP address of the proxy server.
+ - This IP will not be validated. The download job will be created even for invalid I(proxy_server).
+ Please check the results of the job for error details.
+ - This is required when I(proxy_support) is C(ParametersProxy).
+ type: str
+ proxy_port:
+ description:
+ - The Port for the proxy server.
+ - This is required when I(proxy_support) is C(ParametersProxy).
+ type: int
+ proxy_type:
+ description:
+ - The proxy type of the proxy server.
+ - This is required when I(proxy_support) is C(ParametersProxy).
+ choices: [HTTP, SOCKS]
+ type: str
+ proxy_uname:
+ description: The user name for the proxy server.
+ type: str
+ proxy_passwd:
+ description: The password for the proxy server.
+ type: str
+ job_wait:
+ description: Whether to wait for job completion or not.
+ type: bool
+ default: true
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/main.yml
new file mode 100644
index 000000000..77872e297
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/meta/main.yml
@@ -0,0 +1,20 @@
+galaxy_info:
+ author: "Sachin Apagundi"
+ description: Firmware update from a repository on a network share (CIFS, NFS, HTTP, HTTPS, FTP).
+ company: Dell Technologies
+ license: GPL-3.0-only
+ min_ansible_version: "2.13"
+ platforms:
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/converge.yml
new file mode 100644
index 000000000..161a35cf4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge idrac_firmware for cifsshare
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Update firmware from repository on a CIFS Share
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'cifsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a CIFS Share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a CIFS Share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a CIFS Share in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/cifs_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/converge.yml
new file mode 100644
index 000000000..bc30806f4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/converge.yml
@@ -0,0 +1,101 @@
+---
+- name: Converge idrac_firmware
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Update firmware from repository on HTTPS Share with apply_update as false
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: false
+ catalog_file_name: "Catalog.xml"
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS Share with apply_update as false"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode
+
+ - name: Update firmware from repository on HTTPS Share with ignore_cert_warning as false
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+ ignore_cert_warning: false
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS Share with ignore_cert_warning as false"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode
+
+ - name: Update firmware from repository on HTTPS Share with reboot as false
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: false
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS Share with reboot as false"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode
+
+ - name: Update firmware from repository on HTTPS Share with job_wait as false
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: false
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS Share with job_wait as false"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/default/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/converge.yml
new file mode 100644
index 000000000..a94da723a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge idrac_firmware for ftp share
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Update firmware from repository on a FTP Share
+ ansible.builtin.import_role:
+ name: idrac_firmware
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'ftpshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ catalog_file_name: "Catalog.xml"
+ reboot: true
+ job_wait: true
+ apply_update: true
+
+ - name: "Verifying update firmware from repository on a FTP Share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a FTP Share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a FTP Share in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/ftp_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/converge.yml
new file mode 100644
index 000000000..82df756b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge idrac_firmware for httpshare
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Update firmware from repository on HTTP Share
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTP Share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTP Share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a HTTP Share in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/http_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/converge.yml
new file mode 100644
index 000000000..a94983cae
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge idrac_firmware for httpsshare
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Update firmware from repository on HTTPS Share
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTPS Share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS Share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a HTTPS Share in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/https_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/converge.yml
new file mode 100644
index 000000000..b4bd4bdc1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/converge.yml
@@ -0,0 +1,117 @@
+---
+- name: Converge idrac_firmware for https share via proxy
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Update firmware from repository on a HTTPS via parameter proxy Share
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsproxy') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ proxy_support: "ParametersProxy"
+ proxy_server: "{{ lookup('env', 'proxyserver') }}"
+ proxy_type: "HTTP"
+ proxy_port: 3128
+ proxy_uname: "{{ lookup('env', 'proxyuname') }}"
+ proxy_passwd: "{{ lookup('env', 'proxypass') }}"
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy share in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
+
+ - name: Update firmware from repository on a HTTPS via default proxy Share
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ reboot: true
+ job_wait: true
+ apply_update: true
+ proxy_support: "DefaultProxy"
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTPS via default proxy share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS via default proxy share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a HTTPS via default proxy share in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
+
+ - name: Update firmware from repository on a HTTPS via parameter proxy Share with proxy_type as SOCKS
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsproxy') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ proxy_support: "ParametersProxy"
+ proxy_server: "{{ lookup('env', 'proxyserversocks') }}"
+ proxy_type: "SOCKS"
+ proxy_port: 1080
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy with proxy_type as SOCKS share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy with proxy_type as SOCKS share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy share with proxy_type as SOCKS in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/httpsproxy_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/converge.yml
new file mode 100644
index 000000000..37b959272
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/converge.yml
@@ -0,0 +1,206 @@
+---
+- name: Converge idrac_firmware for negative scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Updating firmware with an invalid hostname
+ ansible.builtin.import_role:
+ name: idrac_firmware
+ vars:
+ hostname: "invalidHostname"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ share_name: "{{ lookup('env', 'httpshare') }}"
+ catalog_file_name: "Catalog.xml"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ ignore_errors: true
+ register: idrac_firmware_result
+
+ - name: "Verifying Updating firmware with an invalid hostname"
+ ansible.builtin.assert:
+ that:
+ - "'unreachable iDRAC IP' in idrac_firmware_out.msg"
+
+ - name: Updating firmware with an invalid username
+ ansible.builtin.import_role:
+ name: idrac_firmware
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "invalidUsername"
+ password: "{{ lookup('env', 'password') }}"
+ share_name: "{{ lookup('env', 'httpshare') }}"
+ catalog_file_name: "Catalog.xml"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ ignore_errors: true
+ register: idrac_firmware_result
+
+ - name: "Verifying Updating firmware with an invalid username"
+ ansible.builtin.assert:
+ that:
+ - "'Incorrect username' in idrac_firmware_out.msg"
+
+ - name: Updating firmware with an invalid password
+ ansible.builtin.import_role:
+ name: idrac_firmware
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "invalidPassword"
+ share_name: "{{ lookup('env', 'httpshare') }}"
+ catalog_file_name: "Catalog.xml"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ ignore_errors: true
+ register: idrac_firmware_result
+
+ - name: "Verifying Updating firmware with an invalid password"
+ ansible.builtin.assert:
+ that:
+ - "'password' in idrac_firmware_out.msg"
+
+ - name: Updating firmware with an invalid ca_path
+ ansible.builtin.import_role:
+ name: idrac_firmware
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ share_name: "{{ lookup('env', 'httpshare') }}"
+ ca_path: "{{ lookup('env', 'capath') }}"
+ catalog_file_name: "Catalog.xml"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ ignore_errors: true
+ register: idrac_firmware_result
+
+ - name: "Verifying Updating firmware with an invalid ca_path"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Firmware update failed."
+
+ - name: Updating firmware with catalog file without extension
+ ansible.builtin.import_role:
+ name: idrac_firmware
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ share_name: "{{ lookup('env', 'httpshare') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: Catalog
+ ignore_errors: true
+ register: idrac_firmware_result
+
+ - name: "Verifying Updating firmware with catalog file without extension"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "catalog_file_name should be an XML file."
+
+ - name: Update firmware from repository on HTTPS Share with invalid share_user
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "invalidUser"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTPS Share with invalid share_user"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+
+ - name: Update firmware from repository on HTTPS Share with invalid share_password
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsshare') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "invalidPassword"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+ register: idrac_firmware_result
+
+ - name: "Verifying update firmware from repository on a HTTPS Share with invalid share_password"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+
+ - name: Update firmware from repository on a HTTPS via parameter proxy Share with invalid proxy_uname
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsproxy') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ proxy_support: "ParametersProxy"
+ proxy_server: "{{ lookup('env', 'proxyserver') }}"
+ proxy_type: "HTTP"
+ proxy_port: 3128
+ proxy_uname: "invalidUname"
+ proxy_passwd: "{{ lookup('env', 'proxypass') }}"
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy share with invalid proxy_uname"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+
+ - name: Update firmware from repository on a HTTPS via parameter proxy Share with invalid proxy_passwd
+ ansible.builtin.import_role:
+ name: "idrac_firmware"
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ share_name: "{{ lookup('env', 'httpsproxy') }}"
+ share_user: "{{ lookup('env', 'shareuser') }}"
+ share_password: "{{ lookup('env', 'sharepassword') }}"
+ reboot: true
+ job_wait: true
+ apply_update: true
+ proxy_support: "ParametersProxy"
+ proxy_server: "{{ lookup('env', 'proxyserver') }}"
+ proxy_type: "HTTP"
+ proxy_port: 3128
+ proxy_uname: "{{ lookup('env', 'proxyuname') }}"
+ proxy_passwd: "invalidPasswd"
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a HTTPS via parameter proxy share with invalid proxy_passwd"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/negative_scenarios/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/converge.yml
new file mode 100644
index 000000000..89e55838c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/converge.yml
@@ -0,0 +1,37 @@
+---
+- name: Converge idrac_firmware for nfsshare
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Update firmware from repository on a NFS Share
+ ansible.builtin.import_role:
+ name: idrac_firmware
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ share_name: "{{ lookup('env', 'nfsshare') }}"
+ validate_certs: false
+ reboot: true
+ job_wait: true
+ apply_update: true
+ catalog_file_name: "Catalog.xml"
+
+ - name: "Verifying update firmware from repository on a NFS Share in check mode"
+ ansible.builtin.assert:
+ that: idrac_firmware_out.msg == "Changes found to commit!"
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Verifying update firmware from repository on a NFS Share in normal mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Successfully updated the firmware."
+ when: not ansible_check_mode and idrac_firmware_out.changed
+
+ - name: "Verifying update firmware from repository on a NFS Share in idempotence mode"
+ ansible.builtin.assert:
+ that:
+ - idrac_firmware_out.msg == "Unable to complete the operation because the catalog name entered has either unsupported firmware packages
+ or same version installed on the server."
+ when: not ansible_check_mode and not idrac_firmware_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/molecule/nfs_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tasks/main.yml
new file mode 100644
index 000000000..c994373ce
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tasks/main.yml
@@ -0,0 +1,27 @@
+---
+# tasks file for idrac_firmware
+- name: Call iDRAC Firmware upgrade
+ dellemc.openmanage.idrac_firmware:
+ idrac_ip: "{{ hostname }}"
+ idrac_port: "{{ https_port }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ https_timeout }}"
+ share_name: "{{ share_name | default(omit) }}"
+ share_user: "{{ share_user | default(omit) }}"
+ share_password: "{{ share_password | default(omit) }}"
+ job_wait: "{{ job_wait }}"
+ catalog_file_name: "{{ catalog_file_name }}"
+ ignore_cert_warning: "{{ ignore_cert_warning }}"
+ apply_update: "{{ apply_update }}"
+ reboot: "{{ reboot }}"
+ proxy_support: "{{ proxy_support }}"
+ proxy_server: "{{ proxy_server | default(omit) }}"
+ proxy_type: "{{ proxy_type | default(omit) }}"
+ proxy_port: "{{ proxy_port | default(omit) }}"
+ proxy_uname: "{{ proxy_uname | default(omit) }}"
+ proxy_passwd: "{{ proxy_passwd | default(omit) }}"
+ register: "idrac_firmware_out"
+ delegate_to: "{{ idrac_firmware_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/test.yml
new file mode 100644
index 000000000..12bb9ffc6
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Firmware update using catalog for idrac
+- hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_firmware
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_firmware/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/vars/main.yml
new file mode 100644
index 000000000..ff6d7325f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_firmware/vars/main.yml
@@ -0,0 +1,3 @@
+---
+# vars file for idrac_firmware
+idrac_firmware_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/README.md
new file mode 100644
index 000000000..dfe49351f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/README.md
@@ -0,0 +1,767 @@
+# idrac_gather_facts
+
+Role to gather facts from iDRAC
+
+## Requirements
+------------
+
+### Development
+Requirements to develop and contribute to the role.
+```
+python
+ansible
+molecule
+docker
+```
+### Production
+Requirements to use the role.
+```
+python
+ansible
+```
+### Ansible collections
+Collections required to use the role.
+```
+dellemc.openmanage
+ansible.utils
+```
+
+## Role Variables
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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.<br>- Prior to collection version 5.0.0, I(validate_certs) is C(False) by default.</td>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>computer_system_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Computer system id.</td>
+ </tr>
+ <tr>
+ <td>manager_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Manager/BMC id.</td>
+ </tr>
+ <tr>
+ <td>target</td>
+ <td>false</td>
+ <td>- System <br></td>
+ <td>- System <br> - BIOS <br> - Controller <br> - CPU <br> - Enclosure <br> - EnclosureEMM <br> - Fan <br>
+ - Firmware <br> - HostNIC <br> - License <br> - Memory <br> - NIC <br> - PCIeSSDBackPlane <br>
+ - PowerSupply <br> - PresenceAndStatusSensor <br> - Sensors_Battery <br> - Sensors_Intrusion <br>
+ - Sensors_Voltage <br> - VirtualDisk <br> - PCIeDevice <br> - PhysicalDisk <br> - SystemMetrics<br> - SecureBoot</td>
+ <td>list</td>
+ <td>Target component for which information needs to be gathered.
+ <ul>
+ <li>C(BIOS) lists the BIOS information.</li>
+ <li>C(Chassis) lists the chassis.</li>
+ <li>C(Controller) lists the available controllers for iDRAC.</li>
+ <li>C(CPU) lists the system processors.</li>
+ <li>C(Enclosure) lists the enclosures.</li>
+ <li>C(EnclosureEMM) lists the enclosure management module specific data.</li>
+ <li>C(Fan) lists the fans.</li>
+ <li>C(Firmware) lists the firmware inventories.</li>
+ <li>C(HostNIC) lists the host NIC.</li>
+ <li>C(IDRAC) lists the attributes for iDRAC.</li>
+ <li>C(License) lists the license information.</li>
+ <li>C(Manager) lists the manager resources.</li>
+ <li>C(Memory) lists the memory device specific data.</li>
+ <li>C(NetworkAdapter) lists the network adapters.</li>
+ <li>C(NetworkPort) lists the network ports.</li>
+ <li>C(NetworkDeviceFunction) lists the network device functions.</li>
+ <li>C(NIC) lists NIC device specific data.</li>
+ <li>C(PCIeSSDBackPlane) lists PCIeSSD back plane specific data.</li>
+ <li>C(PowerSupply) lists data specific to the Power Supply devices in the managed system.</li>
+ <li>C(PresenceAndStatusSensor) lists the presence and status sensor specific data.</li>
+ <li>C(PCIeDevice) lists the PCIeDevices.</li>
+ <li>C(PhysicalDisk) lists the physical disks.</li>
+ <li>C(Sensors_Battery) lists the sensors battery information.</li>
+ <li>C(Sensors_Intrusion) lists the sensors intrusion information.</li>
+ <li>C(Sensors_Voltage) lists the sensors voltage information.</li>
+ <li>C(System) lists the ComputerSystem resources for iDRAC.</li>
+ <li>C(SystemMetrics) lists the system metrics.</li>
+ <li>C(ThermalSubSystem) lists the thermal sub system.</li>
+ <li>C(VirtualDisk) lists the virtual disks.</li>
+ <li>C(VirtualMedia) lists the virtual media.</li>
+ <li>C(SecureBoot) lists the secure boot specific data.</li>
+ </ul>
+ </td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>system</td>
+ <td>{"BIOSReleaseDate": "03/22/2022", "BaseBoardChassisSlot": "1", "BatteryRollupStatus": "OK", "BladeGeometry": "SingleWidth,FullHeight", "CMCIP": "1.2.3.4", "CPURollupStatus": "Unknown", "ChassisModel": "", "ChassisName": "", "ChassisServiceTag": "SVCTAG1", "ChassisSystemHeightUnit": 7, "CurrentRollupStatus": "OK", "EstimatedExhaustTemperatureCelsius": 255, "EstimatedSystemAirflowCFM": 255, "ExpressServiceCode": "SERVICECODE1", "FanRollupStatus": null, "IDSDMRollupStatus": null, "Id": "System.Embedded.1", "IntrusionRollupStatus": null, "IsOEMBranded": "False", "LastSystemInventoryTime": "2019-08-09T13:23:32+00:00", "LastUpdateTime": "2022-06-10T20:19:30+00:00", "LicensingRollupStatus": "OK", "ManagedSystemSize": "7 U", "MaxCPUSockets": 2, "MaxDIMMSlots": 24, "MaxPCIeSlots": 3, "MemoryOperationMode": "OptimizerMode", "Name": "DellSystem", "NodeID": "SVCTAG2", "PSRollupStatus": null, "PlatformGUID": "325a364f-c0b6-4b80-3010-00484c4c4544", "PopulatedDIMMSlots": 2, "PopulatedPCIeSlots": 3, "PowerCapEnabledState": "Disabled", "SDCardRollupStatus": "OK", "SELRollupStatus": "OK", "ServerAllocationWatts": 18, "ServerOS.1.HostName": "MINWINPC", "ServerOS.1.OEMOSVersion": "", "ServerOS.1.OSName": "", "ServerOS.1.OSVersion": "", "ServerOS.1.ProductKey": "", "ServerOS.1.ServerPoweredOnTime": 0, "StorageRollupStatus": "OK", "SysMemErrorMethodology": "Multi-bitECC", "SysMemFailOverState": "NotInUse", "SysMemLocation": "SystemBoardOrMotherboard", "SysMemPrimaryStatus": "OK", "SystemGeneration": "14G Modular", "SystemID": 1893, "SystemRevision": "I", "TempRollupStatus": "OK", "TempStatisticsRollupStatus": "OK", "UUID": "4c4c4544-0048-3010-804b-b6c04f365a32", "VoltRollupStatus": "OK", "smbiosGUID": "44454c4c-4800-1030-804b-12345678abcd"}</td>
+ <td>Response facts details for system and operating system.</td>
+ </tr>
+ <tr>
+ <td>bios</td>
+ <td>{"@Redfish.Settings": {"SupportedApplyTimes": ["OnReset", "AtMaintenanceWindowStart", "InMaintenanceWindowOnReset"]}, "Attributes": {"AcPwrRcvry": "Last", "AdddcSetting": "Disabled", "AesNi": "Enabled", "AssetTag": "", "AuthorizeDeviceFirmware": "Disabled", "AvxIccpPregrant": "IccpHeavy128", "BootMode": "Bios", "BootSeqRetry": "Enabled", "CECriticalSEL": "Disabled", "ConTermType": "Vt100Vt220", "ControlledTurbo": "Disabled", "ControlledTurboMinusBin": 0, "CorrEccSmi": "Enabled", "CpuInterconnectBusLinkPower": "Enabled", "CpuInterconnectBusSpeed": "MaxDataRate", "CurrentEmbVideoState": "Enabled", "DcuIpPrefetcher": "Enabled", "DcuStreamerPrefetcher": "Enabled", "DeadLineLlcAlloc": "Enabled", "DellWyseP25BIOSAccess": "Enabled", "DirectoryAtoS": "Disabled", "DramRefreshDelay": "Performance", "DynamicCoreAllocation": "Disabled", "EmbSata": "AhciMode", "EmbVideo": "Enabled", "EnergyPerformanceBias": "BalancedPerformance", "ErrPrompt": "Enabled", "ExtSerialConnector": "Serial1", "FailSafeBaud": "115200", "ForceInt10": "Disabled", "GenericUsbBoot": "Disabled", "HddFailover": "Disabled", "HddPlaceholder": "Disabled", "InBandManageabilityInterface": "Enabled", "IntelTxt": "Off", "InternalUsb": "On", "IoatEngine": "Disabled", "LlcPrefetch": "Disabled", "MemFrequency": "MaxPerf", "MemOpMode": "OptimizerMode", "MemPatrolScrub": "Standard", "MemRefreshRate": "1x", "MemTest": "Disabled", "MemoryMappedIOH": "56TB", "MmioAbove4Gb": "Enabled", "MonitorMwait": "Enabled", "NativeTrfcTiming": "Enabled", "NodeInterleave": "Disabled", "NumLock": "On", "NvmeMode": "NonRaid", "OneTimeBootMode": "Disabled", "OneTimeBootSeqDev": "Floppy.iDRACVirtual.1-1", "OneTimeHddSeqDev": "", "OppSrefEn": "Disabled", "OsWatchdogTimer": "Disabled", "PCIRootDeviceUnhide": "Disabled", "PPROnUCE": "Enabled", "PasswordStatus": "Unlocked", "PcieAspmL1": "Enabled", "PowerCycleRequest": "None", "Proc1Brand": "Intel(R) Xeon(R) Bronze 3204 CPU @ 1.90GHz", "Proc1Id": "6-55-7", "Proc1L2Cache": "6x1 MB", "Proc1L3Cache": "8448 KB", "Proc1MaxMemoryCapacity": "1 TB", "Proc1Microcode": "0x5003302", "Proc1NumCores": 6, "Proc2Brand": "Intel(R) Xeon(R) Bronze 3204 CPU @ 1.90GHz", "Proc2Id": "6-55-7", "Proc2L2Cache": "6x1 MB", "Proc2L3Cache": "8448 KB", "Proc2MaxMemoryCapacity": "1 TB", "Proc2Microcode": "0x5003302", "Proc2NumCores": 6, "ProcAdjCacheLine": "Enabled", "ProcBusSpeed": "9.60 GT/s", "ProcC1E": "Enabled", "ProcCStates": "Enabled", "ProcConfigTdp": "Nominal", "ProcCoreSpeed": "1.90 GHz", "ProcCores": "All", "ProcHwPrefetcher": "Enabled", "ProcPwrPerf": "SysDbpm", "ProcVirtualization": "Enabled", "ProcX2Apic": "Enabled", "PwrButton": "Enabled", "RedirAfterBoot": "Enabled", "RedundantOsBoot": "Disabled", "RedundantOsLocation": "None", "RedundantOsState": "Visible", "SHA256SetupPassword": "", "SHA256SetupPasswordSalt": "", "SHA256SystemPassword": "", "SHA256SystemPasswordSalt": "", "SataPortA": "Auto", "SataPortACapacity": "N/A", "SataPortADriveType": "Unknown Device", "SataPortAModel": "Unknown", "SataPortB": "Auto", "SataPortBCapacity": "N/A", "SataPortBDriveType": "Unknown Device", "SataPortBModel": "Unknown", "SataPortC": "Auto", "SataPortCCapacity": "N/A", "SataPortCDriveType": "Unknown Device", "SataPortCModel": "Unknown", "SataPortD": "Auto", "SataPortDCapacity": "N/A", "SataPortDDriveType": "Unknown Device", "SataPortDModel": "Unknown", "SataPortE": "Auto", "SataPortECapacity": "N/A", "SataPortEDriveType": "Unknown Device", "SataPortEModel": "Unknown", "SataPortF": "Auto", "SataPortFCapacity": "N/A", "SataPortFDriveType": "Unknown Device", "SataPortFModel": "Unknown", "SecureBoot": "Disabled", "SecureBootMode": "DeployedMode", "SecureBootPolicy": "Standard", "SecurityFreezeLock": "Enabled", "SerialComm": "Off", "SerialPortAddress": "Com1", "SetBootOrderDis": "", "SetBootOrderEn": "Floppy.iDRACVirtual.1-1,Optical.iDRACVirtual.1-1", "SetBootOrderFqdd1": "", "SetBootOrderFqdd10": "", "SetBootOrderFqdd11": "", "SetBootOrderFqdd12": "", "SetBootOrderFqdd13": "", "SetBootOrderFqdd14": "", "SetBootOrderFqdd15": "", "SetBootOrderFqdd16": "", "SetBootOrderFqdd2": "", "SetBootOrderFqdd3": "", "SetBootOrderFqdd4": "", "SetBootOrderFqdd5": "", "SetBootOrderFqdd6": "", "SetBootOrderFqdd7": "", "SetBootOrderFqdd8": "", "SetBootOrderFqdd9": "", "SetLegacyHddOrderFqdd1": "", "SetLegacyHddOrderFqdd10": "", "SetLegacyHddOrderFqdd11": "", "SetLegacyHddOrderFqdd12": "", "SetLegacyHddOrderFqdd13": "", "SetLegacyHddOrderFqdd14": "", "SetLegacyHddOrderFqdd15": "", "SetLegacyHddOrderFqdd16": "", "SetLegacyHddOrderFqdd2": "", "SetLegacyHddOrderFqdd3": "", "SetLegacyHddOrderFqdd4": "", "SetLegacyHddOrderFqdd5": "", "SetLegacyHddOrderFqdd6": "", "SetLegacyHddOrderFqdd7": "", "SetLegacyHddOrderFqdd8": "", "SetLegacyHddOrderFqdd9": "", "SetupPassword": null, "Slot1": "Enabled", "Slot2": "Enabled", "Slot3": "Enabled", "SnoopHldOff": "Roll2KCycles", "SriovGlobalEnable": "Disabled", "SubNumaCluster": "Disabled", "SysMemSize": "32 GB", "SysMemSpeed": "2133 Mhz", "SysMemType": "ECC DDR4", "SysMemVolt": "1.20 V", "SysMfrContactInfo": "www.dell.com", "SysPassword": null, "SysProfile": "PerfPerWattOptimizedDapc", "SystemBiosVersion": "2.14.2", "SystemCpldVersion": "1.0.4", "SystemManufacturer": "Dell Inc.", "SystemMeVersion": "4.1.4.700", "SystemModelName": "PowerEdge MX740c", "SystemServiceTag": "SVCTAG3", "TpmCommand": "None", "TpmFirmware": "TpmFirmware", "TpmInfo": "Type: 1.2-NTC", "TpmPpiBypassClear": "Disabled", "TpmPpiBypassProvision": "Disabled", "TpmSecurity": "Off", "TpmStatus": "Unknown", "UefiComplianceVersion": "2.7", "UefiVariableAccess": "Standard", "UncoreFrequency": "DynamicUFS", "UpiPrefetch": "Enabled", "UsbManagedPort": "On", "UsbPorts": "AllOn", "VideoMem": "16 MB", "WorkloadProfile": "NotAvailable", "WriteCache": "Disabled", "WriteDataCrc": "Disabled"}}</td>
+ <td>Response facts details for bios.</td>
+ </tr>
+ <tr>
+ <td>controller</td>
+ <td>[{
+ "@Redfish.Settings": {
+ "SettingsObject": {},
+ "SupportedApplyTimes": [
+ "Immediate",
+ "OnReset",
+ "AtMaintenanceWindowStart",
+ "InMaintenanceWindowOnReset"
+ ]
+ },
+ "Assembly": {},
+ "CacheSummary": {
+ "TotalCacheSizeMiB": 0
+ },
+ "ControllerRates": {
+ "ConsistencyCheckRatePercent": null,
+ "RebuildRatePercent": null
+ },
+ "Description": "Integrated AHCI controller 1",
+ "FirmwareVersion": "2.6.13.3025",
+ "Id": "AHCI.Integrated.1-1",
+ "Identifiers": [
+ {
+ "DurableName": null,
+ "DurableNameFormat": null
+ }
+ ],
+ "Links": {
+ "PCIeFunctions": []
+ },
+ "Manufacturer": "DELL",
+ "Model": "BOSS-S1",
+ "Name": "BOSS-S1",
+ "Oem": {
+ "Dell": {
+ "DellStorageController": {
+ "AlarmState": "AlarmNotSupported",
+ "AutoConfigBehavior": "NotApplicable",
+ "BackgroundInitializationRatePercent": null,
+ "BatteryLearnMode": null,
+ "BootVirtualDiskFQDD": null,
+ "CacheSizeInMB": 0,
+ "CachecadeCapability": "NotSupported",
+ "CheckConsistencyMode": null,
+ "ConnectorCount": 0,
+ "ControllerBootMode": null,
+ "ControllerFirmwareVersion": "2.6.13.3025",
+ "ControllerMode": null,
+ "CopybackMode": null,
+ "CurrentControllerMode": "NotSupported",
+ "Device": "0",
+ "DeviceCardDataBusWidth": "4x or x4",
+ "DeviceCardSlotLength": "Other",
+ "DeviceCardSlotType": "M.2 Socket 3 (Mechanical Key M)",
+ "DriverVersion": null,
+ "EncryptionCapability": "None",
+ "EncryptionMode": "None",
+ "EnhancedAutoImportForeignConfigurationMode": null,
+ "KeyID": null,
+ "LastSystemInventoryTime": "2023-12-31T12:25:07+00:00",
+ "LastUpdateTime": "2023-12-31T18:50:12+00:00",
+ "LoadBalanceMode": null,
+ "MaxAvailablePCILinkSpeed": null,
+ "MaxDrivesInSpanCount": 2,
+ "MaxPossiblePCILinkSpeed": null,
+ "MaxSpansInVolumeCount": 1,
+ "MaxSupportedVolumesCount": 1,
+ "PCISlot": null,
+ "PatrolReadIterationsCount": 0,
+ "PatrolReadMode": null,
+ "PatrolReadRatePercent": null,
+ "PatrolReadState": "Unknown",
+ "PatrolReadUnconfiguredAreaMode": null,
+ "PersistentHotspare": "NotApplicable",
+ "RAIDMode": "None",
+ "RealtimeCapability": "Incapable",
+ "ReconstructRatePercent": null,
+ "RollupStatus": "OK",
+ "SASAddress": "0",
+ "SecurityStatus": "EncryptionNotCapable",
+ "SharedSlotAssignmentAllowed": "NotApplicable",
+ "SlicedVDCapability": "NotSupported",
+ "SpindownIdleTimeSeconds": 0,
+ "SupportControllerBootMode": "NotSupported",
+ "SupportEnhancedAutoForeignImport": "NotSupported",
+ "SupportRAID10UnevenSpans": "NotSupported",
+ "SupportedInitializationTypes": [
+ "Fast"
+ ],
+ "SupportsLKMtoSEKMTransition": "No",
+ "T10PICapability": "NotSupported"
+ }
+ }
+ },
+ "SpeedGbps": 6.0,
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ },
+ "SupportedControllerProtocols": [
+ "PCIe"
+ ],
+ "SupportedDeviceProtocols": [
+ "SATA"
+ ],
+ "SupportedRAIDTypes": [
+ "RAID1"
+ ]
+ }
+ ]</td>
+ <td>Response facts details for controller.</td>
+ </tr>
+ <tr>
+ <td>cpu</td>
+ <td>[{"Description": "Represents the properties of a Processor attached to this System", "Id": "CPU.Socket.1", "InstructionSet": "x86-64", "Manufacturer": "Intel", "MaxSpeedMHz": 4000, "Model": "Intel(R) Xeon(R) Bronze 3204 CPU @ 1.90GHz", "Name": "CPU 1", "Oem": {"Dell": {"DellAccelerators": null, "DellProcessor": {"CPUFamily": "Intel(R)Xeon(TM)", "CPUStatus": "CPUEnabled", "Cache1Associativity": "8-WaySet-Associative", "Cache1ErrorMethodology": "Parity", "Cache1InstalledSizeKB": 384, "Cache1Level": "L1", "Cache1Location": "Internal", "Cache1PrimaryStatus": "OK", "Cache1SRAMType": "Unknown", "Cache1SizeKB": 384, "Cache1Type": "Unified", "Cache1WritePolicy": "WriteBack", "Cache2Associativity": "16-WaySet-Associative", "Cache2ErrorMethodology": "Single-bitECC", "Cache2InstalledSizeKB": 6144, "Cache2Level": "L2", "Cache2Location": "Internal", "Cache2PrimaryStatus": "OK", "Cache2SRAMType": "Unknown", "Cache2SizeKB": 6144, "Cache2Type": "Unified", "Cache2WritePolicy": "WriteBack", "Cache3Associativity": "FullyAssociative", "Cache3ErrorMethodology": "Single-bitECC", "Cache3InstalledSizeKB": 8448, "Cache3Level": "L3", "Cache3Location": "Internal", "Cache3PrimaryStatus": "OK", "Cache3SRAMType": "Unknown", "Cache3SizeKB": 8448, "Cache3Type": "Unified", "Cache3WritePolicy": "WriteBack", "CurrentClockSpeedMhz": 1900, "ExternalBusClockSpeedMhz": 9600, "HyperThreadingCapable": "No", "HyperThreadingEnabled": "No", "Id": "CPU.Socket.1", "LastSystemInventoryTime": "2019-08-09T13:23:32+00:00", "LastUpdateTime": "2021-09-14T20:31:00+00:00", "Name": "DellProcessor", "TurboModeCapable": "No", "TurboModeEnabled": "No", "VirtualizationTechnologyCapable": "Yes", "VirtualizationTechnologyEnabled": "Yes", "Volts": "1.8"}, "PowerMetrics": null, "ThermalMetrics": null}}, "OperatingSpeedMHz": 1900, "ProcessorArchitecture": "x86", "ProcessorId": {"EffectiveFamily": "6", "EffectiveModel": "85", "IdentificationRegisters": "0x00050657", "MicrocodeInfo": "0x5003302", "Step": "7", "VendorId": "GenuineIntel"}, "ProcessorType": "CPU", "Socket": "CPU.Socket.1", "Status": {"Health": null, "State": "UnavailableOffline"}, "TotalCores": 6, "TotalEnabledCores": 6, "TotalThreads": 6, "TurboState": "Disabled", "Version": "Model 85 Stepping 7"}]</td>
+ <td>Response facts details for cpu.</td>
+ </tr>
+ <tr>
+ <td>enclosure</td>
+ <td>[{"AssetName": null, "Connector": 0, "Id": "Enclosure.Internal.0-0:RAID.Mezzanine.1C-1", "LastSystemInventoryTime": "2019-08-09T13:23:32+00:00", "LastUpdateTime": "2022-09-23T23:44:26+00:00", "Name": "DellEnclosure", "ServiceTag": null, "SlotCount": 6, "TempProbeCount": 0, "Version": "4.35", "WiredOrder": 0}]</td>
+ <td>Response facts details for enclosure.</td>
+ </tr>
+ <tr>
+ <td>enclosure_emm</td>
+ <td>[{"DeviceDescription": "EMM.Slot.0:Enclosure.Modular.4:NonRAID.Mezzanine.1C-1", "FQDD": "EMM.Slot.0:Enclosure.Modular.4:NonRAID.Mezzanine.1C-1", "Id": "EMM.Slot.0:Enclosure.Modular.4:NonRAID.Mezzanine.1C-1", "InstanceID": "EMM.Slot.0:Enclosure.Modular.4:NonRAID.Mezzanine.1C-1", "Name": "DellEnclosureEMM", "PartNumber": null, "PrimaryStatus": "OK", "Revision": "2.40", "State": "Ready"}]</td>
+ <td>Response facts details for enclosure_emm.</td>
+ </tr>
+ <tr>
+ <td>fan</td>
+ <td>[{"Description": "Represents fan properties of the chassis", "HotPluggable": true, "Id": "Fan.Embedded.6A", "Location": {"PartLocation": {"LocationType": "Bay", "ServiceLabel": "System Board Fan6A"}}, "Name": "Fan 6A", "PhysicalContext": "SystemBoard", "SpeedPercent": {"SpeedRPM": 11640}, "Status": {"Health": "OK", "State": "Enabled"}}]</td>
+ <td>Response facts details for fan.</td>
+ </tr>
+ <tr>
+ <td>firmware</td>
+ <td>[{"Description": "Represents Firmware Inventory", "Id": "Previous-108255-22.00.6__NIC.Embedded.2-1-1", "Name": "Broadcom Gigabit Ethernet BCM5720 - AB:CD:EF:GH:IJ:02", "Oem": {"Dell": {"DellSoftwareInventory": {"BuildNumber": 0, "Classifications": ["Firmware"], "ComponentID": "108255", "ComponentType": "FRMW", "Description": "The DellSoftwareInventory resource is a representation of an available device firmware in the managed system.", "DeviceID": "165F", "ElementName": "Broadcom Gigabit Ethernet BCM5720 - AB:CD:EF:GH:IJ:02", "HashValue": "56fa85676e6d570f714fb659f202371f1c570263b680e2d40d16059acfa9e3e6", "Id": "DCIM:PREVIOUS_0x23_701__NIC.Embedded.2-1-1", "IdentityInfoType": ["OrgID:ComponentType:VendorID:DeviceID:SubVendorID:SubDeviceID"], "IdentityInfoValue": ["DCIM:firmware:14E4:165F:1028:08FF"], "InstallationDate": "NA", "IsEntity": true, "MajorVersion": 22, "MinorVersion": 0, "Name": "DellSoftwareInventory", "PLDMCapabilitiesDuringUpdate": "0x00000000", "PLDMFDPCapabilitiesDuringUpdate": "0x00000000", "RevisionNumber": 6, "RevisionString": null, "SidebandUpdateCapable": false, "Status": "AvailableForInstallation", "SubDeviceID": "08FF", "SubVendorID": "1028", "VendorID": "14E4", "impactsTPMmeasurements": true}}}, "ReleaseDate": "2022-01-07T00:00:00Z", "SoftwareId": "108255", "Status": {"Health": "OK", "State": "Enabled"}, "Updateable": true, "Version": "22.00.6"}, {"Description": "Represents Firmware Inventory", "Id": "Previous-159-1.7.5__BIOS.Setup.1-1", "Name": "BIOS", "Oem": {"Dell": {"DellSoftwareInventory": {"BuildNumber": 0, "Classifications": ["BIOS/FCode"], "ComponentID": "159", "ComponentType": "BIOS", "Description": "The DellSoftwareInventory resource is a representation of an available device firmware in the managed system.", "DeviceID": null, "ElementName": "BIOS", "HashValue": "37e196d6b1c25ffc58f1c5c5a80a748932d22ddfbf72eedda05fbe788f57d641", "Id": "DCIM:PREVIOUS_0x23_741__BIOS.Setup.1-1", "IdentityInfoType": ["OrgID:ComponentType:ComponentID"], "IdentityInfoValue": ["DCIM:BIOS:159"], "InstallationDate": "NA", "IsEntity": true, "MajorVersion": 1, "MinorVersion": 7, "Name": "DellSoftwareInventory", "PLDMCapabilitiesDuringUpdate": "0x00000000", "PLDMFDPCapabilitiesDuringUpdate": "0x00000000", "RevisionNumber": 5, "RevisionString": null, "SidebandUpdateCapable": false, "Status": "AvailableForInstallation", "SubDeviceID": null, "SubVendorID": null, "VendorID": null, "impactsTPMmeasurements": true}}}, "ReleaseDate": "2022-09-16T00:00:00Z", "SoftwareId": "159", "Status": {"Health": "OK", "State": "Enabled"}, "Updateable": true, "Version": "1.7.5"}, {"Description": "Represents Firmware Inventory", "Id": "Previous-25227-6.00.02.00__iDRAC.Embedded.1-1", "Name": "Integrated Dell Remote Access Controller", "Oem": {"Dell": {"DellSoftwareInventory": {"BuildNumber": 7, "Classifications": ["Firmware"], "ComponentID": "25227", "ComponentType": "FRMW", "Description": "The DellSoftwareInventory resource is a representation of an available device firmware in the managed system.", "DeviceID": null, "ElementName": "Integrated Dell Remote Access Controller", "HashValue": null, "Id": "DCIM:PREVIOUS_0x23_iDRAC.Embedded.1-1_0x23_IDRACinfo", "IdentityInfoType": ["OrgID:ComponentType:ComponentID"], "IdentityInfoValue": ["DCIM:firmware:25227"], "InstallationDate": "NA", "IsEntity": true, "MajorVersion": 6, "MinorVersion": 0, "Name": "DellSoftwareInventory", "PLDMCapabilitiesDuringUpdate": "0x00000000", "PLDMFDPCapabilitiesDuringUpdate": "0x00000000", "RevisionNumber": 2, "RevisionString": null, "SidebandUpdateCapable": false, "Status": "AvailableForInstallation", "SubDeviceID": null, "SubVendorID": null, "VendorID": null, "impactsTPMmeasurements": false}}}, "ReleaseDate": "2022-08-11T00:00:00Z", "SoftwareId": "25227", "Status": {"Health": "OK", "State": "Enabled"}, "Updateable": true, "Version": "6.00.02.00"}]</td>
+ <td>Response facts details for firmware.</td>
+ </tr>
+ <tr>
+ <td>hostnic</td>
+ <td>[{"Description": "Management for Host Interface", "ExternallyAccessible": false, "HostInterfaceType": "NetworkHostInterface", "Id": "Host.1", "InterfaceEnabled": false, "Name": "Managed Host Interface 1"}]</td>
+ <td>Response facts details for hostnic.</td>
+ </tr>
+ <tr>
+ <td>license</td>
+ <td>[{"AuthorizationScope": "Service", "Description": "iDRAC9 x5 Enterprise Evaluation License", "DownloadURI": "/redfish/v1/LicenseService/Licenses/1188PA_girish_narasimhap/DownloadURI", "EntitlementId": "1188PA_girish_narasimhap", "ExpirationDate": "2023-02-23T00:00:00-06:00", "Id": "1188PA_girish_narasimhap", "InstallDate": null, "LicenseInfoURI": "", "LicenseOrigin": "Installed", "LicenseType": "Trial", "Links": {}, "Name": "1188PA_girish_narasimhap", "Removable": true, "Status": {"Health": "Warning", "State": "Enabled"}}]</td>
+ <td>Response facts details for license.</td>
+ </tr>
+ <tr>
+ <td>nic</td>
+ <td>[{"AutoNeg": true, "Description": "Embedded NIC 1 Port 1 Partition 1", "EthernetInterfaceType": "Physical", "FQDN": null, "FullDuplex": true, "HostName": null, "IPv4Addresses": [], "IPv6AddressPolicyTable": [], "IPv6Addresses": [], "IPv6DefaultGateway": null, "IPv6StaticAddresses": [], "Id": "NIC.Embedded.1-1-1", "InterfaceEnabled": true, "LinkStatus": "LinkUp", "Links": {"Chassis": {}}, "MACAddress": "AB:CD:EF:GH:IJ:02", "MTUSize": null, "MaxIPv6StaticAddresses": null, "Name": "System Ethernet Interface", "NameServers": [], "PermanentMACAddress": "AB:CD:EF:GH:IJ:02", "SpeedMbps": 1000, "Status": {"Health": "OK", "State": "Enabled"}, "UefiDevicePath": "PciRoot(0x0)/Pci(0x1C,0x5)/Pci(0x0,0x0)", "VLAN": {}}, {"AutoNeg": false, "Description": "Embedded NIC 1 Port 2 Partition 1", "EthernetInterfaceType": "Physical", "FQDN": null, "FullDuplex": false, "HostName": null, "IPv4Addresses": [], "IPv6AddressPolicyTable": [], "IPv6Addresses": [], "IPv6DefaultGateway": null, "IPv6StaticAddresses": [], "Id": "NIC.Embedded.2-1-1", "InterfaceEnabled": true, "LinkStatus": "LinkDown", "Links": {"Chassis": {}}, "MACAddress": "AB:CD:EF:GH:IJ:02", "MTUSize": null, "MaxIPv6StaticAddresses": null, "Name": "System Ethernet Interface", "NameServers": [], "PermanentMACAddress": "AB:CD:EF:GH:IJ:02", "SpeedMbps": 0, "Status": {"Health": "OK", "State": "Enabled"}, "UefiDevicePath": "PciRoot(0x0)/Pci(0x1C,0x5)/Pci(0x0,0x1)", "VLAN": {}}]</td>
+ <td>Response facts details for nic.</td>
+ </tr>
+ <tr>
+ <td>memory</td>
+ <td>[{"AllowedSpeedsMHz": [3200], "Assembly": {}, "BaseModuleType": "RDIMM", "BusWidthBits": 72, "CacheSizeMiB": 0, "CapacityMiB": 8192, "DataWidthBits": 64, "Description": "DIMM A1", "DeviceLocator": "DIMM A1", "Enabled": true, "ErrorCorrection": "MultiBitECC", "FirmwareRevision": null, "Id": "DIMM.Socket.A1", "Links": {"Chassis": {}, "Oem": {"Dell": {"CPUAffinity": []}}, "Processors": []}, "LogicalSizeMiB": 0, "Manufacturer": "Hynix Semiconductor", "MaxTDPMilliWatts": [], "MemoryDeviceType": "DDR4", "MemorySubsystemControllerManufacturerID": null, "MemorySubsystemControllerProductID": null, "MemoryType": "DRAM", "Metrics": {}, "ModuleManufacturerID": "0xad80", "ModuleProductID": null, "Name": "DIMM A1", "NonVolatileSizeMiB": 0, "Oem": {"Dell": {"DellMemory": {"BankLabel": "A", "Id": "DIMM.Socket.A1", "LastSystemInventoryTime": "2023-01-31T12:00:45+00:00", "LastUpdateTime": "2021-02-11T21:30:07+00:00", "ManufactureDate": "Mon May 04 07:00:00 2020 UTC", "MemoryTechnology": "DRAM", "Model": "DDR4 DIMM", "Name": "DellMemory", "RemainingRatedWriteEndurancePercent": null, "SystemEraseCapability": "NotSupported"}}}, "OperatingMemoryModes": ["Volatile"], "OperatingSpeedMhz": 2666, "PartNumber": "PARTNUM-XN", "RankCount": 1, "SerialNumber": "SERIAL1", "Status": {"Health": "OK", "State": "Enabled"}, "VolatileSizeMiB": 8192}]</td>
+ <td>Response facts details for memory.</td>
+ </tr>
+ <tr>
+ <td>backplane</td>
+ <td>[{"Description": "An instance of DellPCIeSSDBackPlane will have PCIeSSD back plane specific data.", "FirmwareVersion": "3.72", "Id": "Enclosure.Internal.0-2", "Name": "DellPCIeSSDBackPlane", "PCIExpressGeneration": "Gen 4", "SlotCount": 8, "WiredOrder": 2}]</td>
+ <td>Response facts details for backplane.</td>
+ </tr>
+ <tr>
+ <td>power_supply</td>
+ <td>[{"Assembly": {}, "Description": "An instance of PowerSupply", "FirmwareVersion": "00.17.28", "HotPluggable": true, "Id": "PSU.Slot.1", "InputNominalVoltageType": "AC240V", "InputRanges": [{"CapacityWatts": 1400.0, "NominalVoltageType": "AC240V"}], "LineInputStatus": "Normal", "Manufacturer": "DELL", "Metrics": {}, "Model": "PWR SPLY,1400W,RDNT,LTON", "Name": "PS1 Status", "Oem": {"Dell": {"DellPowerSupply": {"ActiveInputVoltage": "Unknown", "IsSwitchingSupply": true, "OperationalStatus": ["OK"], "RequestedState": "NotApplicable"}, "DellPowerSupplyView": {"DetailedState": "Presence Detected", "DeviceDescription": "Power Supply 1", "LastSystemInventoryTime": "2023-01-31T12:00:45+00:00", "LastUpdateTime": "2023-03-09T15:58:41+00:00", "PMBusMonitoring": "Capable", "Range1MaxInputPowerWatts": 1568, "RedMinNumberNeeded": 1, "RedTypeOfSet": ["N+1", "Sparing"], "RedundancyStatus": "Unknown"}}}, "PartNumber": "SPARE2", "PowerCapacityWatts": 1400.0, "PowerSupplyType": "AC", "SerialNumber": "ABCD1", "SparePartNumber": "SPARE1", "Status": {"Health": "OK", "State": "Enabled"}}]</td>
+ <td>Response facts details for power_supply.</td>
+ </tr>
+ <tr>
+ <td>presence_and_status_sensor</td>
+ <td>[{"CurrentState": "Present", "Description": "An instance of DellPresenceAndStatusSensor will have presence and status sensor specific data.", "DeviceID": "iDRAC.Embedded.1#VFLASHSD", "ElementName": "VFLASH SD", "Id": "iDRAC.Embedded.1_0x23_VFLASHSD", "Name": "DellPresenceAndStatusSensor", "SensorType": "Other"}]</td>
+ <td>Response facts details for presence_and_status_sensor.</td>
+ </tr>
+ <tr>
+ <td>sensor_battery</td>
+ <td>{"CurrentState": "Good", "Description": "An instance of DellSensor will represent a sensor, a hardware device that is capable of measuring the characteristics of a physical property.", "ElementName": "System Board CMOS Battery", "EnabledState": "Enabled", "HealthState": "OK", "Id": "iDRAC.Embedded.1_0x23_SystemBoardCMOSBattery", "Links": {"ComputerSystem": {}}, "Name": "DellSensor", "SensorType": "Other"}</td>
+ <td>Response facts details for sensor_battery.</td>
+ </tr>
+ <tr>
+ <td>intrusion_sensor</td>
+ <td>{"PhysicalSecurity": {"IntrusionSensor": "Normal"}}</td>
+ <td>Response facts details for intrusion_sensor.</td>
+ </tr>
+ <tr>
+ <td>virtual_disk</td>
+ <td>[{"@Redfish.Settings": {"SettingsObject": {}, "SupportedApplyTimes": ["Immediate", "OnReset", "AtMaintenanceWindowStart", "InMaintenanceWindowOnReset"]}, "BlockSizeBytes": 512, "CapacityBytes": 240057409536, "Description": "Disk 0 on Integrated AHCI controller 1", "DisplayName": null, "Encrypted": null, "EncryptionTypes": [], "Id": "Disk.Direct.0-0:AHCI.Integrated.1-1", "Identifiers": [], "MediaSpanCount": null, "Name": "SSD 0", "Operations": [], "OptimumIOSizeBytes": null, "RAIDType": null, "ReadCachePolicy": null, "Status": {"Health": "OK", "HealthRollup": "OK", "State": "Enabled"}, "VolumeType": "RawDevice", "WriteCachePolicy": null}, {"@Redfish.Settings": {"SettingsObject": {}, "SupportedApplyTimes": ["Immediate", "OnReset", "AtMaintenanceWindowStart", "InMaintenanceWindowOnReset"]}, "BlockSizeBytes": 512, "CapacityBytes": 240057409536, "Description": "Disk 1 on Integrated AHCI controller 1", "DisplayName": null, "Encrypted": null, "EncryptionTypes": [], "Id": "Disk.Direct.1-1:AHCI.Integrated.1-1", "Identifiers": [], "MediaSpanCount": null, "Name": "SSD 1", "Operations": [], "OptimumIOSizeBytes": null, "RAIDType": null, "ReadCachePolicy": null, "Status": {"Health": "OK", "HealthRollup": "OK", "State": "Enabled"}, "VolumeType": "RawDevice", "WriteCachePolicy": null}]</td>
+ <td>Response facts details for virtual_disk.</td>
+ </tr>
+ <tr>
+ <td>pcie_device</td>
+ <td>
+ {"AssetTag": null, "Description": "Integrated Matrox G200eW3 Graphics Controller", "DeviceType": "SingleFunction", "FirmwareVersion": "", "Id": "3-0", "Manufacturer": "Matrox Electronics Systems Ltd.", "Model": null, "Name": "Integrated Matrox G200eW3 Graphics Controller", "PCIeFunctions": {}, "PartNumber": null, "SKU": null, "SerialNumber": null, "Status": {"Health": "OK", "HealthRollup": "OK", "State": "Enabled"}}, {"AssetTag": null, "Description": "PERC H730P MX", "DeviceType": "SingleFunction", "FirmwareVersion": "25.5.9.0001", "Id": "59-0", "Manufacturer": "Broadcom / LSI", "Model": null, "Name": "PERC H730P MX", "PCIeFunctions": {}, "PartNumber": "PART2", "SKU": null, "SerialNumber": "SERIALN1", "Status": {"Health": "OK", "HealthRollup": "OK", "State": "Enabled"}
+ }</td>
+ <td>Response facts details for pcie_device.</td>
+ </tr>
+ <tr>
+ <td>physical_disk</td>
+ <td>[{"BlockSizeBytes": 512, "CapableSpeedGbs": 6, "CapacityBytes": 240057409536, "Description": "Disk 1 on Integrated AHCI controller 1", "EncryptionAbility": "None", "EncryptionStatus": "Unencrypted", "FailurePredicted": false, "HotspareType": "None", "Id": "Disk.Direct.1-1:AHCI.Integrated.1-1", "Identifiers": [{"DurableName": null, "DurableNameFormat": null}], "Identifiers@odata.count": 1, "Location": [], "LocationIndicatorActive": null, "Manufacturer": "INTEL", "MediaType": "SSD", "Model": "SSDMODEL1", "Name": "SSD 1", "NegotiatedSpeedGbs": 6, "Oem": {"Dell": {"DellPhysicalDisk": {"AvailableSparePercent": null, "Certified": "NotApplicable", "Connector": 0, "CryptographicEraseCapable": "Capable", "Description": "An instance of DellPhysicalDisk will have Physical Disk specific data.", "DeviceProtocol": null, "DeviceSidebandProtocol": null, "DriveFormFactor": "M.2", "EncryptionProtocol": "None", "ErrorDescription": null, "ErrorRecoverable": "NotApplicable", "ForeignKeyIdentifier": null, "FreeSizeInBytes": 240057409536, "Id": "Disk.Direct.1-1:AHCI.Integrated.1-1", "LastSystemInventoryTime": "2023-03-04T05:50:09+00:00", "LastUpdateTime": "2023-02-15T16:32:30+00:00", "ManufacturingDay": 0, "ManufacturingWeek": 0, "ManufacturingYear": 0, "Name": "DellPhysicalDisk", "NonRAIDDiskCachePolicy": "Unknown", "OperationName": "None", "OperationPercentCompletePercent": 0, "PCIeCapableLinkWidth": "None", "PCIeNegotiatedLinkWidth": "None", "PPID": "TW-0919J9-PIHIT-8AB-02K7-A00", "PowerStatus": "On", "PredictiveFailureState": "SmartAlertAbsent", "ProductID": null, "RAIDType": "Unknown", "RaidStatus": "NonRAID", "SASAddress": "Not Applicable", "Slot": 1, "SystemEraseCapability": "CryptographicErasePD", "T10PICapability": "NotSupported", "UsedSizeInBytes": 0, "WWN": "Not Applicable"}}}, "Operations": [], "PartNumber": "TW-0919J9-PIHIT-8AB-02K7-A00", "PhysicalLocation": {"PartLocation": {"LocationOrdinalValue": 1, "LocationType": "Slot"}}, "PredictedMediaLifeLeftPercent": 100, "Protocol": "SATA", "Revision": "N201DL43", "RotationSpeedRPM": null, "SerialNumber": "SERIAL2", "Status": {"Health": "OK", "HealthRollup": "OK", "State": "Enabled"}, "WriteCacheEnabled": false}]</td>
+ <td>Response facts details for physical_disk.</td>
+ </tr>
+ <tr>
+ <td>secure_boot</td>
+ <td>{
+ "Actions": {
+ "#SecureBoot.ResetKeys": {
+ "ResetKeysType@Redfish.AllowableValues": [
+ "ResetAllKeysToDefault",
+ "DeleteAllKeys",
+ "DeletePK",
+ "ResetPK",
+ "ResetKEK",
+ "ResetDB",
+ "ResetDBX"
+ ],
+ "target": "/redfish/v1/Systems/System.Embedded.1/SecureBoot/Actions/SecureBoot.ResetKeys"
+ },
+ "Oem": {}
+ },
+ "Description": "UEFI Secure Boot",
+ "Id": "SecureBoot",
+ "Name": "UEFI Secure Boot",
+ "Oem": {
+ "Dell": {
+ "Certificates": {},
+ "FirmwareImageHashes": {}
+ }
+ },
+ "SecureBootCurrentBoot": "Disabled",
+ "SecureBootDatabases": [
+ {
+ "Actions": {
+ "#SecureBootDatabase.ResetKeys": {
+ "ResetKeysType@Redfish.AllowableValues": [
+ "ResetAllKeysToDefault",
+ "DeleteAllKeys"
+ ],
+ "target": "/redfish/v1/Systems/System.Embedded.1/SecureBoot/SecureBootDatabases/db/Actions/SecureBootDatabase.ResetKeys"
+ }
+ },
+ "Certificates": [
+ {
+ "CertificateString": null,
+ "CertificateType": "PEM",
+ "CertificateUsageTypes": [
+ "BIOS"
+ ],
+ "Description": "SecureBoot Certificate",
+ "Id": "StdSecbootpolicy.3",
+ "Issuer": {
+ "City": "Redmond",
+ "CommonName": "Microsoft Corporation Third Party Marketplace Root",
+ "Country": "US",
+ "Organization": "Microsoft Corporation",
+ "State": "Washington"
+ },
+ "Name": "SecureBoot Certificate",
+ "SerialNumber": "SERIAL00001",
+ "Subject": {
+ "City": "Redmond",
+ "CommonName": "Microsoft Corporation UEFI CA 2011",
+ "Country": "US",
+ "Organization": "Microsoft Corporation",
+ "State": "Washington"
+ },
+ "ValidNotAfter": "2026-6-27T21:32:45+00:00",
+ "ValidNotBefore": "2011-6-27T21:22:45+00:00"
+ },
+ {
+ "CertificateString": null,
+ "CertificateType": "PEM",
+ "CertificateUsageTypes": [
+ "BIOS"
+ ],
+ "Description": "SecureBoot Certificate",
+ "Id": "StdSecbootpolicy.4",
+ "Issuer": {
+ "City": "Redmond",
+ "CommonName": "Microsoft Root Certificate Authority 2010",
+ "Country": "US",
+ "Organization": "Microsoft Corporation",
+ "State": "Washington"
+ },
+ "Name": "SecureBoot Certificate",
+ "SerialNumber": "SERIAL000002",
+ "Subject": {
+ "City": "Redmond",
+ "CommonName": "Microsoft Windows Production PCA 2011",
+ "Country": "US",
+ "Organization": "Microsoft Corporation",
+ "State": "Washington"
+ },
+ "ValidNotAfter": "2026-10-19T18:51:42+00:00",
+ "ValidNotBefore": "2011-10-19T18:41:42+00:00"
+ },
+ {
+ "CertificateString": null,
+ "CertificateType": "PEM",
+ "CertificateUsageTypes": [
+ "BIOS"
+ ],
+ "Description": "SecureBoot Certificate",
+ "Id": "StdSecbootpolicy.5",
+ "Issuer": {
+ "City": "Palo Alto",
+ "Country": "US",
+ "Organization": "VMware, Inc.",
+ "State": "California"
+ },
+ "Name": "SecureBoot Certificate",
+ "SerialNumber": "SERIAL3",
+ "Subject": {
+ "City": "Palo Alto",
+ "Country": "US",
+ "Organization": "VMware, Inc.",
+ "State": "California"
+ },
+ "ValidNotAfter": "2019-12-31T17:16:05+00:00",
+ "ValidNotBefore": "2008-10-16T17:16:05+00:00"
+ },
+ {
+ "CertificateString": null,
+ "CertificateType": "PEM",
+ "CertificateUsageTypes": [
+ "BIOS"
+ ],
+ "Description": "SecureBoot Certificate",
+ "Id": "StdSecbootpolicy.6",
+ "Issuer": {
+ "City": "Palo Alto",
+ "CommonName": "VMware Secure Boot Signing",
+ "Country": "US",
+ "Organization": "VMware, Inc.",
+ "State": "California"
+ },
+ "Name": "SecureBoot Certificate",
+ "SerialNumber": "SERIAL00005",
+ "Subject": {
+ "City": "Palo Alto",
+ "CommonName": "VMware Secure Boot Signing",
+ "Country": "US",
+ "Organization": "VMware, Inc.",
+ "State": "California"
+ },
+ "ValidNotAfter": "2037-10-19T06:47:59+00:00",
+ "ValidNotBefore": "2017-10-24T06:47:59+00:00"
+ }
+ ],
+ "DatabaseId": "db",
+ "Description": "SecureBootDatabase",
+ "Id": "db",
+ "Name": "SecureBootDatabase",
+ "Signatures": {}
+ },
+ {
+ "Actions": {
+ "#SecureBootDatabase.ResetKeys": {
+ "ResetKeysType@Redfish.AllowableValues": [
+ "ResetAllKeysToDefault",
+ "DeleteAllKeys"
+ ],
+ "target": "/redfish/v1/Systems/System.Embedded.1/SecureBoot/SecureBootDatabases/dbx/Actions/SecureBootDatabase.ResetKeys"
+ }
+ },
+ "Certificates": [],
+ "DatabaseId": "dbx",
+ "Description": "SecureBootDatabase",
+ "Id": "dbx",
+ "Name": "SecureBootDatabase",
+ "Signatures": {}
+ },
+ {
+ "Actions": {
+ "#SecureBootDatabase.ResetKeys": {
+ "ResetKeysType@Redfish.AllowableValues": [
+ "ResetAllKeysToDefault",
+ "DeleteAllKeys"
+ ],
+ "target": "/redfish/v1/Systems/System.Embedded.1/SecureBoot/SecureBootDatabases/KEK/Actions/SecureBootDatabase.ResetKeys"
+ }
+ },
+ "Certificates": [
+ {
+ "CertificateString": null,
+ "CertificateType": "PEM",
+ "CertificateUsageTypes": [
+ "BIOS"
+ ],
+ "Description": "SecureBoot Certificate",
+ "Id": "StdSecbootpolicy.2",
+ "Issuer": {
+ "City": "Redmond",
+ "CommonName": "Microsoft Corporation Third Party Marketplace Root",
+ "Country": "US",
+ "Organization": "Microsoft Corporation",
+ "State": "Washington"
+ },
+ "Name": "SecureBoot Certificate",
+ "SerialNumber": "SERIAL000005",
+ "Subject": {
+ "City": "Redmond",
+ "CommonName": "Microsoft Corporation KEK CA 2011",
+ "Country": "US",
+ "Organization": "Microsoft Corporation",
+ "State": "Washington"
+ },
+ "ValidNotAfter": "2022-6-24T20:51:29+00:00",
+ "ValidNotBefore": "2011-6-24T20:41:29+00:00"
+ }
+ ],
+ "DatabaseId": "KEK",
+ "Description": "SecureBootDatabase",
+ "Id": "KEK",
+ "Name": "SecureBootDatabase",
+ "Signatures": {}
+ },
+ {
+ "Actions": {
+ "#SecureBootDatabase.ResetKeys": {
+ "ResetKeysType@Redfish.AllowableValues": [
+ "ResetAllKeysToDefault",
+ "DeleteAllKeys"
+ ],
+ "target": "/redfish/v1/Systems/System.Embedded.1/SecureBoot/SecureBootDatabases/PK/Actions/SecureBootDatabase.ResetKeys"
+ }
+ },
+ "Certificates": [
+ {
+ "CertificateString": null,
+ "CertificateType": "PEM",
+ "CertificateUsageTypes": [
+ "BIOS"
+ ],
+ "Description": "SecureBoot Certificate",
+ "Id": "StdSecbootpolicy.1",
+ "Issuer": {
+ "City": "Round Rock",
+ "CommonName": "Dell Inc. Platform Key",
+ "Country": "US",
+ "Organization": "Dell Inc.",
+ "State": "Texas"
+ },
+ "Name": "SecureBoot Certificate",
+ "SerialNumber": "12345ABCD",
+ "Subject": {
+ "City": "Round Rock",
+ "CommonName": "Dell Inc. Platform Key",
+ "Country": "US",
+ "Organization": "Dell Inc.",
+ "State": "Texas"
+ },
+ "ValidNotAfter": "2021-2-2T17:27:36+00:00",
+ "ValidNotBefore": "2016-2-2T17:17:37+00:00"
+ }
+ ],
+ "DatabaseId": "PK",
+ "Description": "SecureBootDatabase",
+ "Id": "PK",
+ "Name": "SecureBootDatabase",
+ "Signatures": {}
+ }
+ ],
+ "SecureBootEnable": false,
+ "SecureBootMode": "DeployedMode"
+ }</td>
+ <td>Response facts details for Secure Boot.</td>
+ </tr>
+</tbody>
+</table>
+
+## Examples
+-----
+```
+- name: iDRAC gather facts for System, BIOS, Controller, CPU, Enclosure.
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target:
+ - System
+ - BIOS
+ - Controller
+ - CPU
+ - Enclosure
+
+- name: Print the System details
+ ansible.builtin.debug:
+ var: system
+
+```
+```
+# Get specific controllers
+- name: Get all controllers
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target:
+ - Controller
+
+- name: Fetch BOSS controllers
+ ansible.builtin.debug:
+ msg: "{{ controller | selectattr('Model', 'contains', 'BOSS') | list }}"
+
+- name: Fetch controller with specific id
+ ansible.builtin.debug:
+ msg: "{{ controller | selectattr('Id', 'equalto', 'AHCI.Integrated.1-1') | list }}"
+
+```
+```
+- name: iDRAC gather facts for EnclosureEMM, Fan, Firmware, HostNIC, License.
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target:
+ - EnclosureEMM
+ - Fan
+ - Firmware
+ - HostNIC
+ - License
+
+- name: Print the firmware details
+ ansible.builtin.debug:
+ var: firmware
+
+```
+```
+- name: iDRAC gather facts for Memory, NIC, PCIeSSDBackPlane, PowerSupply, PresenceAndStatusSensor, SecureBoot.
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target:
+ - Memory
+ - NIC
+ - PCIeSSDBackPlane
+ - PowerSupply
+ - PresenceAndStatusSensor
+ - SecureBoot
+
+- name: Print the secure boot details
+ ansible.builtin.debug:
+ var: secure_boot
+```
+```
+- name: iDRAC gather facts for Sensors_Battery, Sensors_Intrusion, Sensors_Voltage, VirtualDisk, PCIeDevice, PhysicalDisk, SystemMetrics using environment variables IDRAC_USERNAME and IDRAC_PASSWORD.
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "192.1.2.1"
+ # IDRAC_USERNAME and IDRAC_PASSWORD set in env
+ ca_path: "/path/to/ca_cert.pem"
+ target:
+ - Sensors_Battery
+ - Sensors_Intrusion
+ - Sensors_Voltage
+ - VirtualDisk
+ - PCIeDevice
+ - PhysicalDisk
+ - SystemMetrics
+
+- name: Print the system metrics
+ ansible.builtin.debug:
+ var: system_metrics
+```
+## Author Information
+------------------
+
+Dell Technologies <br>
+Felix Stephen A (felix.s@dell.com) <br>
+Jagadeesh N V (jagadeesh.n.v@dell.com)
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/defaults/main.yml
new file mode 100644
index 000000000..0ff68d419
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/defaults/main.yml
@@ -0,0 +1,8 @@
+---
+https_port: 443
+validate_certs: true
+https_timeout: 30
+target:
+ - System
+computer_system_id: ""
+manager_id: ""
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/handlers/main.yml
new file mode 100644
index 000000000..033de9080
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_gather_facts
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/argument_specs.yml
new file mode 100644
index 000000000..de3515f26
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/argument_specs.yml
@@ -0,0 +1,110 @@
+---
+argument_specs:
+ main:
+ version_added: 7.4.0
+ short_description: Role to get the facts from the iDRAC Server
+ description:
+ - Role to fetch the server facts about a different components available in
+ the PowerEdge Servers.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ username:
+ type: str
+ description: iDRAC username.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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.
+ - Prior to collection version 5.0.0, I(validate_certs) is C(False) by
+ default.
+ type: bool
+ default: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate
+ to be used for the validation.
+ type: path
+ https_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ computer_system_id:
+ description: Computer system id
+ type: str
+ manager_id:
+ description: Manager/BMC id
+ type: str
+ target:
+ description:
+ - Target component for which information needs to be gathered.
+ - C(BIOS) lists the BIOS information.
+ - C(Chassis) lists the chassis.
+ - C(Controller) lists the available controllers for iDRAC.
+ - C(CPU) lists the system processors.
+ - C(Enclosure) lists the enclosures.
+ - C(EnclosureEMM) lists the enclosure management module specific data.
+ - C(Fan) lists the fans.
+ - C(Firmware) lists the firmware inventories.
+ - C(HostNIC) lists the host NIC.
+ - C(IDRAC) lists the attributes for iDRAC.
+ - C(License) lists the license information.
+ - C(Manager) lists the manager resources.
+ - C(Memory) lists the memory device specific data.
+ - C(NetworkAdapter) lists the network adapters.
+ - C(NetworkPort) lists the network ports.
+ - C(NetworkDeviceFunction) lists the network device functions.
+ - C(NIC) lists NIC device specific data.
+ - C(PCIeSSDBackPlane) lists PCIeSSD back plane specific data.
+ - C(PowerSupply) lists data specific to the Power Supply devices in
+ the managed system.
+ - C(PresenceAndStatusSensor) lists the presence and status sensor
+ specific data.
+ - C(PCIeDevice) lists the PCIeDevices.
+ - C(PhysicalDisk) lists the physical disks.
+ - C(Sensors_Battery) lists the sensors battery information.
+ - C(Sensors_Intrusion) lists the sensors intrusion information.
+ - C(Sensors_Voltage) lists the sensors voltage information.
+ - C(System) lists the ComputerSystem resources for iDRAC.
+ - C(SystemMetrics) lists the system metrics.
+ - C(ThermalSubSystem) lists the thermal sub system.
+ - C(VirtualDisk) lists the virtual disks.
+ - C(VirtualMedia) lists the virtual media.
+ - C(SecureBoot) lists the secure boot specific data.
+ type: list
+ choices:
+ - IDRAC
+ - System
+ - BIOS
+ - Controller
+ - CPU
+ - Enclosure
+ - EnclosureEMM
+ - Fan
+ - Firmware
+ - HostNIC
+ - License
+ - Memory
+ - NIC
+ - PCIeSSDBackPlane
+ - PowerSupply
+ - PresenceAndStatusSensor
+ - Sensors_Battery
+ - Sensors_Intrusion
+ - Sensors_Voltage
+ - VirtualDisk
+ - PCIeDevice
+ - PhysicalDisk
+ - SystemMetrics
+ - SecureBoot
+ default: System
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/main.yml
new file mode 100644
index 000000000..f1d10da13
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/meta/main.yml
@@ -0,0 +1,22 @@
+galaxy_info:
+ author: |
+ "Felix Stephen
+ Jagadeesh N V"
+ description: Role to gather facts
+ company: Dell Technologies
+ license: GPL-3.0-only
+ min_ansible_version: "2.13"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/converge.yml
new file mode 100644
index 000000000..adb6fcf5f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/converge.yml
@@ -0,0 +1,44 @@
+---
+- name: Converge idrac_gather_facts for PCIeSSDBackPlane
+ hosts: all
+ connection: local
+ gather_facts: true
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - PCIeSSDBackPlane
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the PCIeSSDBackPlane component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert backplane dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ backplane | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/backplane_assert.yml
+ with_items: "{{ backplane }}"
+ loop_control:
+ loop_var: backplane_data
+ when: backplane | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/backplane/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/converge.yml
new file mode 100644
index 000000000..491d49d42
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/converge.yml
@@ -0,0 +1,81 @@
+---
+- name: Converge idrac gather facts for bios
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - BIOS
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the BIOS component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert bios dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ bios | length > 0 }}"
+
+ - name: Fetching BIOS info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Bios"
+ validate_certs: false
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: bios_result
+ no_log: true
+
+ - name: Response filter
+ ansible.builtin.set_fact:
+ api_response:
+ "{{ bios_result.json | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.type', '@odata.id', 'SettingsObject', 'Actions', 'AttributeRegistry', 'Description',
+ 'Id', 'Links', 'Name']) }}"
+ vars:
+ jquery: "Oem.Dell.DellSystem"
+
+ - name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ bios.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+ - name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: bios[item]}) }}"
+ loop: "{{ bios.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - bios[item] != api_response[item]
+ - item not in exclude_keys
+
+ - name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/bios/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/converge.yml
new file mode 100644
index 000000000..e7059f6a7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/converge.yml
@@ -0,0 +1,40 @@
+---
+- name: Converge idrac_gather_facts for controller
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Controller
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: ["Description"]
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the Controller component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert controller dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ controller | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/controller_assert.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/controller/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/converge.yml
new file mode 100644
index 000000000..8f75cd73f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/converge.yml
@@ -0,0 +1,45 @@
+---
+- name: Converge idrac_gather_facts for CPU
+ hosts: all
+ connection: local
+ gather_facts: false
+ vars:
+ hostname: "100.96.25.90"
+ username: "root"
+ password: "Dell_123$"
+ validate_certs: false
+ target:
+ - CPU
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the CPU component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert cpu dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ cpu | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/cpu_assert.yml
+ with_items: "{{ cpu }}"
+ loop_control:
+ loop_var: cpu_data
+ when: cpu | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/cpu/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/converge.yml
new file mode 100644
index 000000000..3d3f3ed1d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/converge.yml
@@ -0,0 +1,95 @@
+---
+- name: Converge idrac_gather_facts
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - System
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: ["ServerOS.1.ServerPoweredOnTime"]
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the System component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert system dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ system | length > 0 }}"
+
+ - name: Fetching System info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}"
+ validate_certs: false
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: system_result
+ no_log: true
+
+ - name: Fetching operating system info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/Managers/System.Embedded.1/Attributes?$select=ServerOS.*" # verification firmware version 5.00.00
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: os_result
+ no_log: true
+
+ - name: Response filter
+ ansible.builtin.set_fact:
+ api_response:
+ "{{ system_result.json | json_query(jquery) | combine(os_result.json.Attributes) |
+ ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
+ vars:
+ jquery: "Oem.Dell.DellSystem"
+
+ - name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ system.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+ - name: Set a Diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: system[item]}) }}"
+ loop: "{{ system.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - system[item] != api_response[item]
+ - item not in exclude_keys
+
+ - name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/default/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/converge.yml
new file mode 100644
index 000000000..f83d84ac7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/converge.yml
@@ -0,0 +1,44 @@
+---
+- name: Converge idrac_gather_facts for Enclosure
+ hosts: all
+ connection: local
+ gather_facts: true
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Enclosure
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the Enclosure component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert enclosure dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ enclosure | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/enclosure_assert.yml
+ with_items: "{{ enclosure }}"
+ loop_control:
+ loop_var: enclosure_data
+ when: enclosure | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosure/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/converge.yml
new file mode 100644
index 000000000..9bddda5a7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/converge.yml
@@ -0,0 +1,38 @@
+---
+- name: Converge idrac_gather_facts for EnclosureEMM
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - EnclosureEMM
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the EnclosureEMM component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/enclosureemm_assert.yml
+ with_items: "{{ enclosure_emm }}"
+ loop_control:
+ loop_var: enclosureemm_data
+ when: enclosure_emm | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/enclosureemm/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/converge.yml
new file mode 100644
index 000000000..bdd47a873
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/converge.yml
@@ -0,0 +1,38 @@
+---
+- name: Converge idrac_gather_facts for Fan
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Fan
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: ["SpeedPercent"]
+
+ tasks:
+ - name: Gather Facts for the Fan component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/fan_assert.yml
+ with_items: "{{ fan }}"
+ loop_control:
+ loop_var: fan_data
+ when: fan | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/fan/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/converge.yml
new file mode 100644
index 000000000..88047ce5c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/converge.yml
@@ -0,0 +1,44 @@
+---
+- name: Converge idrac_gather_facts for Firmware
+ hosts: all
+ connection: local
+ gather_facts: true
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Firmware
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the Firmware component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert firmware dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ firmware | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/firmware_assert.yml
+ with_items: "{{ firmware }}"
+ loop_control:
+ loop_var: firmware_data
+ when: firmware | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/firmware/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/converge.yml
new file mode 100644
index 000000000..1ab1f4911
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge idrac_gather_facts for HostNIC
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - HostNIC
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the HostNIC component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert hostnic dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ hostnic | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/hostnic_assert.yml
+ with_items: "{{ hostnic }}"
+ loop_control:
+ loop_var: hostnic_data
+ when: hostnic | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/hostnic/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/converge.yml
new file mode 100644
index 000000000..2b8788274
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/converge.yml
@@ -0,0 +1,93 @@
+---
+- name: Converge idrac_gather_facts for idrac
+ hosts: all
+ connection: local
+ gather_facts: true
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - IDRAC
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: ["ServerOS.1.ServerPoweredOnTime", "SystemInfo.1.SysTime"]
+
+ tasks:
+ - name: Gather Facts for idrac component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Get System information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_manager }}/Oem/Dell/DellAttributes/System.Embedded.1"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: response_sys_attr
+ no_log: true
+
+ - name: Get Manager information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_manager }}/Oem/Dell/DellAttributes/iDRAC.Embedded.1"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: response_mgr_attr
+ no_log: true
+
+ - name: Get Lifecycle controller information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_manager }}/Oem/Dell/DellAttributes/LifecycleController.Embedded.1"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: response_lc_attr
+ no_log: true
+
+ - name: Set System, Manager, Lifecycle controller facts
+ ansible.builtin.set_fact:
+ api_idrac:
+ api_system_attributes: "{{ response_sys_attr.json.Attributes }}"
+ api_manager_attributes: "{{ response_mgr_attr.json.Attributes }}"
+ api_lifecycle_controller_attributes: "{{ response_lc_attr.json.Attributes }}"
+
+ - name: Call assertion For System Attributes
+ ansible.builtin.include_tasks: ../../tests/asserts/system_assert.yml
+
+ - name: Call assertion For LC Attributes
+ ansible.builtin.include_tasks: ../../tests/asserts/lc_assert.yml
+
+ - name: Call assertion For Manager Attributes
+ ansible.builtin.include_tasks: ../../tests/asserts/manager_assert.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/idrac/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/converge.yml
new file mode 100644
index 000000000..b1fe0419b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge idrac_gather_facts for License
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - License
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the License component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert license dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ license | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/license_assert.yml
+ with_items: "{{ license }}"
+ loop_control:
+ loop_var: license_data
+ when: license | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/license/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/converge.yml
new file mode 100644
index 000000000..5a3909481
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/converge.yml
@@ -0,0 +1,44 @@
+---
+- name: Converge idrac_gather_facts for Memory
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Memory
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the Memory component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert memory dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ memory | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/memory_assert.yml
+ with_items: "{{ memory }}"
+ loop_control:
+ loop_var: memory_data
+ when: memory | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/memory/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/converge.yml
new file mode 100644
index 000000000..b191098a8
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/converge.yml
@@ -0,0 +1,92 @@
+---
+- name: Converge for negative scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: To check for wrong hostname
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "randomHostname"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_gather_facts_err
+
+ - name: Asserting after performing opeartion with invalid hostname
+ ansible.builtin.assert:
+ that:
+ - idrac_gather_facts_connection.status == -1
+
+ - name: To check for wrong username
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "randomUsername"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target: ["Bios"]
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_gather_facts_error
+
+ - name: Asserting after performing opeartion with invalid username
+ ansible.builtin.assert:
+ that:
+ - idrac_gather_facts_connection.status == 401
+
+ - name: To check for wrong password
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "randomPassword"
+ validate_certs: false
+ target: ["Bios"]
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_gather_facts_error
+
+ - name: Asserting after performing opeartion with invalid password
+ ansible.builtin.assert:
+ that:
+ - idrac_gather_facts_connection.status == -1
+
+ - name: To check for wrong system id
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ computer_system_id: "randomSystemID"
+ ignore_errors: true
+ register: idrac_gather_facts_error
+
+ - name: Asserting after performing operation with invalid system id
+ ansible.builtin.assert:
+ that:
+ - "{{ computer_system_id not in system_ids }}"
+
+ - name: To check for wrong manager id
+ ansible.builtin.import_role:
+ name: idrac_gather_facts
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ manager_id: "randomManagerID"
+ target: ["Firmware"]
+ ignore_errors: true
+ register: idrac_gather_facts_error
+
+ - name: Asserting after performing operation with invalid manager id
+ ansible.builtin.assert:
+ that:
+ - "{{ manager_id not in manager_ids }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/negative/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/converge.yml
new file mode 100644
index 000000000..70d00f200
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/converge.yml
@@ -0,0 +1,44 @@
+---
+- name: Converge idrac_gather_facts for NIC
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - NIC
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the NIC component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert nic dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ nic | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/nic_assert.yml
+ with_items: "{{ nic }}"
+ loop_control:
+ loop_var: nic_data
+ when: nic | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/nic/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/converge.yml
new file mode 100644
index 000000000..93de081d3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge idrac_gather_facts for Presence and Status Sensor
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - PresenceAndStatusSensor
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the Presence and Status Sensor
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/passensor_assert.yml
+ with_items: "{{ presence_and_status_sensor }}"
+ loop_control:
+ loop_var: passensor_data
+ when: presence_and_status_sensor | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/passensor/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/converge.yml
new file mode 100644
index 000000000..b87459d13
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge idrac_gather_facts for PCIeDevice component
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - PCIeDevice
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the PCIeDevice
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert pcie device dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ pcie_device | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/pciedevice_assert.yml
+ with_items: "{{ pcie_device }}"
+ loop_control:
+ loop_var: pci_data
+ when: pcie_device | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/pciedevice/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/converge.yml
new file mode 100644
index 000000000..a5b66a7f9
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/converge.yml
@@ -0,0 +1,44 @@
+---
+- name: Converge idrac_gather_facts for Physical Disk
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - PhysicalDisk
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the Physical Disk component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert physical disk dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ physical_disk | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/physicaldisk_assert.yml
+ with_items: "{{ physical_disk }}"
+ loop_control:
+ loop_var: pd_data
+ when: physical_disk | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/physicaldisk/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/converge.yml
new file mode 100644
index 000000000..1fdb5a278
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge idrac_gather_facts for Power Supply
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - PowerSupply
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the Power Supply component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert power supply dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ power_supply | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/powersupply_assert.yml
+ with_items: "{{ power_supply }}"
+ loop_control:
+ loop_var: powersupply_data
+ when: power_supply | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/powersupply/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/converge.yml
new file mode 100644
index 000000000..e4585165e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/converge.yml
@@ -0,0 +1,40 @@
+---
+- name: Converge idrac_gather_facts for SecureBoot
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - SecureBoot
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the Secureboot component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert secureboot supply dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ secure_boot | length > 0 }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/secureboot_assert.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/secureboot/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/converge.yml
new file mode 100644
index 000000000..feee7473e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/converge.yml
@@ -0,0 +1,80 @@
+---
+- name: Converge idrac_gather_facts for Sensors Battery
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Sensors_Battery
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the Sensors Battery component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert sensor battery dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ sensor_battery | length > 0 }}"
+
+ - name: Fetching Sensor Battery info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Oem/Dell/DellSensors/iDRAC.Embedded.1_0x23_SystemBoardCMOSBattery"
+ validate_certs: false
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ no_log: true
+ register: battery_result
+
+ - name: Response filter
+ ansible.builtin.set_fact:
+ api_response:
+ "{{ battery_result.json | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.id', '@odata.type']) }}"
+ vars:
+ jquery: "Oem.Dell.DellSystem"
+
+ - name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ sensor_battery.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+ - name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: sensor_battery[item]}) }}"
+ loop: "{{ sensor_battery.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - sensor_battery[item] != api_response[item]
+ - item not in exclude_keys
+
+ - name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsbattery/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/converge.yml
new file mode 100644
index 000000000..274319cff
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/converge.yml
@@ -0,0 +1,79 @@
+---
+- name: Converge idrac_gather_facts for Sensors Intrusion
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Sensors_Intrusion
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the Sensors Intrusion component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert sensor battery dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ intrusion_sensor | length > 0 }}"
+
+ - name: Fetching Sensor Battery info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}?$select=PhysicalSecurity/IntrusionSensor"
+ validate_certs: false
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ no_log: true
+ register: sensorintrusion_result
+
+ - name: Response filter
+ ansible.builtin.set_fact:
+ api_response:
+ "{{ sensorintrusion_result.json | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.id', '@odata.type']) }}"
+ vars:
+ jquery: "Oem.Dell.DellSystem"
+
+ - name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ intrusion_sensor.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+ - name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: intrusion_sensor[item]}) }}"
+ loop: "{{ intrusion_sensor.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - intrusion_sensor[item] != api_response[item]
+ - item not in exclude_keys
+
+ - name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsintrusion/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/converge.yml
new file mode 100644
index 000000000..16435ef11
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/converge.yml
@@ -0,0 +1,65 @@
+---
+- name: Converge idrac_gather_facts for Voltage Sensors
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - Sensors_Voltage
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the voltage sensor component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert power supply dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ voltages | length > 0 }}"
+
+ - name: Get Sensor Voltage information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}/Power#/Voltages"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: voltage_result
+ no_log: true
+
+ - name: Set Sensor Voltage facts
+ ansible.builtin.set_fact:
+ "api_response":
+ "{{ voltage_result.json.Voltages | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.id', '@odata.type']) }}"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/sensorsvoltage_assert.yml
+ with_items: "{{ voltages }}"
+ loop_control:
+ loop_var: sensorsvoltage_data
+ index_var: index
+ when: voltages | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/sensorsvoltage/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/converge.yml
new file mode 100644
index 000000000..acd31a108
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/converge.yml
@@ -0,0 +1,105 @@
+---
+- name: Converge idrac_gather_facts for Power Supply
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - SystemMetrics
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+
+ tasks:
+ - name: Gather Facts for the System Metrics component
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Assert power metrics dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ power_metrics | length > 0 }}"
+
+ - name: Assert thermal metrics dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ thermal_metrics | length > 0 }}"
+
+ - name: Assert memory metrics dict for length
+ ansible.builtin.assert:
+ that:
+ - "{{ memory_metrics | length > 0 }}"
+
+ - name: Get Thermal Metrics information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}/ThermalSubsystem/ThermalMetrics"
+ validate_certs: "{{ validate_certs }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: response_thermal_metrics
+ no_log: true
+
+ - name: Set Thermal Metrics facts
+ ansible.builtin.set_fact:
+ api_thermal_metrics: "{{ response_thermal_metrics.json |
+ ansible.utils.remove_keys(target=['@odata.context', '@odata.type', '@odata.id', 'DataSourceUri', 'TemperatureReadingsCelsius@odata.count']) }}"
+
+ - name: Call assertion for thermal metrics
+ ansible.builtin.include_tasks: ../../tests/asserts/tmetrics_assert.yml
+
+ - name: Call assertion for memory metrics
+ ansible.builtin.include_tasks: ../../tests/asserts/mmetrics_assert.yml
+ with_items: "{{ memory_metrics }}"
+ loop_control:
+ loop_var: memory_data
+ when: memory_metrics | length > 0
+
+ - name: Get Power Supply information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}/PowerSubsystem/PowerSupplies?$expand=*($levels=1)"
+ validate_certs: "{{ validate_certs }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: response_power_supply
+ no_log: true
+
+ - name: Set query
+ ansible.builtin.set_fact:
+ jq: "[*].Id"
+
+ - name: Get Power Supply Metrics ids
+ ansible.builtin.set_fact:
+ psu_ids: "{{ power_result.json.Members | json_query(jq) }}"
+
+ - name: Call assertion for Power metrics
+ ansible.builtin.include_tasks: ../../tests/asserts/psmetrics_assert.yml
+ with_items: "{{ power_metrics }}"
+ loop_control:
+ loop_var: power_data
+ index_var: index
+ when: power_metrics | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/systemmetrics/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/converge.yml
new file mode 100644
index 000000000..27fd2b829
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge idrac_gather_facts for Virtual Disk
+ hosts: all
+ gather_facts: false
+ vars:
+ hostname: "{{ lookup('env', 'hostname') }}"
+ username: "{{ lookup('env', 'username') }}"
+ password: "{{ lookup('env', 'password') }}"
+ validate_certs: false
+ target:
+ - VirtualDisk
+ idrac_gather_facts_uri_method: "GET"
+ idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ idrac_gather_facts_uri_body_format: "json"
+ idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ idrac_gather_facts_uri_return_content: true
+ diff_data: {}
+ exclude_keys: []
+ api_system: "/redfish/v1/Systems/System.Embedded.1"
+
+ tasks:
+ - name: Gather Facts for the Virtual Disk
+ ansible.builtin.include_role:
+ name: "idrac_gather_facts"
+
+ - name: Call assertion
+ ansible.builtin.include_tasks: ../../tests/asserts/virtualdisk_assert.yml
+ with_items: "{{ virtual_disk }}"
+ loop_control:
+ loop_var: virtualdisk_data
+ when: virtual_disk | length > 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/molecule/virtualdisk/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_attributes_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_attributes_info.yml
new file mode 100644
index 000000000..498acd48a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_attributes_info.yml
@@ -0,0 +1,28 @@
+---
+- name: Get System information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_manager
+ }}/Oem/Dell/DellAttributes/{{ computer_system_id }}"
+ register: sys_attr
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Manager information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_manager
+ }}/Oem/Dell/DellAttributes/iDRAC.Embedded.1"
+ register: mgr_attr
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Lifecycle controller information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_manager
+ }}/Oem/Dell/DellAttributes/LifecycleController.Embedded.1"
+ register: lc_attr
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set System, Manager, Lifecycle controller facts
+ ansible.builtin.set_fact:
+ idrac:
+ system_attributes: "{{ sys_attr.json.Attributes }}"
+ manager_attributes: "{{ mgr_attr.json.Attributes }}"
+ lifecycle_controller_attributes: "{{ lc_attr.json.Attributes }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_backplane_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_backplane_info.yml
new file mode 100644
index 000000000..165eeca81
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_backplane_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get PCIeSSDBackPlane information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Chassis/Oem/Dell/DellPCIeSSDBackPlanes"
+ register: pcie_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set PCIeSSDBackPlane facts
+ ansible.builtin.set_fact:
+ backplane: "{{ pcie_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_battery_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_battery_info.yml
new file mode 100644
index 000000000..2c023a077
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_battery_info.yml
@@ -0,0 +1,12 @@
+---
+- name: Get Sensor Battery information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Oem/Dell/DellSensors/iDRAC.Embedded.1_0x23_SystemBoardCMOSBattery"
+ register: battery_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Sensor Battery facts
+ ansible.builtin.set_fact:
+ "sensor_battery":
+ "{{ battery_result.json | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.id', '@odata.type']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_bios_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_bios_info.yml
new file mode 100644
index 000000000..bca717beb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_bios_info.yml
@@ -0,0 +1,13 @@
+---
+- name: Get BIOS information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Bios"
+ register: bios_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set BIOS facts
+ ansible.builtin.set_fact:
+ bios:
+ "{{ bios_result.json | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.type', '@odata.id', 'SettingsObject', 'Actions', 'AttributeRegistry', 'Description',
+ 'Id', 'Links', 'Name']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_controller_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_controller_info.yml
new file mode 100644
index 000000000..8933343a3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_controller_info.yml
@@ -0,0 +1,38 @@
+---
+- name: Get Storage information.
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}{{ api_system
+ }}/Storage/?$expand=*($levels=1)
+ register: disk_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get all storage controllers.
+ ansible.builtin.set_fact:
+ controllers_list: "{{ disk_result.json.Members | selectattr('Controllers',
+ 'defined') | map(attribute='Controllers') }}"
+
+- name: Select list of values from dictionary
+ ansible.builtin.set_fact:
+ controller_list_temp: "{{ (controller_list_temp | default([])) +
+ [controller_item['@odata.id']] }}"
+ loop: "{{ controllers_list }}"
+ loop_control:
+ loop_var: controller_item
+
+- name: Get Controllers information.
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}{{ each_controller
+ }}?$expand=*($levels=1)
+ loop: "{{ controller_list_temp }}"
+ loop_control:
+ loop_var: each_controller
+ register: result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set All Controllers facts
+ ansible.builtin.set_fact:
+ controller: "{{ result.results | selectattr('json', 'defined') |
+ map(attribute='json') | selectattr('Members', 'defined') |
+ map(attribute='Members') | flatten |
+ ansible.utils.remove_keys(target=['^.*@odata.*$'],
+ matching_parameter='regex') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_cpu_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_cpu_info.yml
new file mode 100644
index 000000000..d6c78cf7d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_cpu_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get CPU information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Processors?$expand=*($levels=1)"
+ register: cpu_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set CPU facts
+ ansible.builtin.set_fact:
+ cpu: "{{ cpu_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Assembly', 'Links']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_emm_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_emm_info.yml
new file mode 100644
index 000000000..d085dce2b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_emm_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get enclosure EMM information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Chassis/Oem/Dell/DellEnclosureEMM"
+ register: emm_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set enclosure EMM facts
+ ansible.builtin.set_fact:
+ enclosure_emm: "{{ emm_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Description', 'Links']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_info.yml
new file mode 100644
index 000000000..57c05333b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_enclosure_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get enclosure information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Chassis/Oem/Dell/DellEnclosures"
+ register: enclosure_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set enclosure facts
+ ansible.builtin.set_fact:
+ enclosure: "{{ enclosure_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Links', 'Description']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_fan_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_fan_info.yml
new file mode 100644
index 000000000..772cfb1b1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_fan_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get Fan information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_chassis }}/ThermalSubsystem/Fans?$expand=*($levels=1)"
+ register: fan_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Fan facts
+ ansible.builtin.set_fact:
+ fan: "{{ fan_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_firmware_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_firmware_info.yml
new file mode 100644
index 000000000..f979a07dd
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_firmware_info.yml
@@ -0,0 +1,12 @@
+---
+- name: Get Firmware information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/UpdateService/FirmwareInventory?$expand=*($levels=1)"
+ register: firmware_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Firmware facts
+ ansible.builtin.set_fact:
+ firmware:
+ "{{ firmware_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type',
+ 'Classifications@odata.count', 'IdentityInfoType@odata.count', 'IdentityInfoValue@odata.count']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_host_nic_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_host_nic_info.yml
new file mode 100644
index 000000000..3f17fde1a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_host_nic_info.yml
@@ -0,0 +1,12 @@
+---
+- name: Get HostNIC information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_manager }}/HostInterfaces?$expand=*($levels=1)"
+ register: nic_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set HostNIC facts
+ ansible.builtin.set_fact:
+ hostnic:
+ "{{ nic_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type',
+ 'HostEthernetInterfaces', 'ManagerEthernetInterface']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_intrusion_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_intrusion_info.yml
new file mode 100644
index 000000000..68cd81a59
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_intrusion_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get Sensor Battery information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_chassis }}?$select=PhysicalSecurity/IntrusionSensor"
+ register: intrusion_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Sensor Battery facts
+ ansible.builtin.set_fact:
+ "intrusion_sensor": "{{ intrusion_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_license_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_license_info.yml
new file mode 100644
index 000000000..2a1044282
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_license_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get License information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/LicenseService/Licenses?$expand=*($levels=1)"
+ register: license_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set License facts
+ ansible.builtin.set_fact:
+ license: "{{ license_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_memory_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_memory_info.yml
new file mode 100644
index 000000000..4537b19d7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_memory_info.yml
@@ -0,0 +1,13 @@
+---
+- name: Get Memory information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Memory?$expand=*($levels=1)"
+ register: memory_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Memory facts
+ ansible.builtin.set_fact:
+ memory:
+ "{{ memory_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type',
+ 'AllowedSpeedsMHz@odata.count', 'CPUAffinity@odata.count', 'Processors@odata.count', 'MaxTDPMilliWatts@odata.count',
+ 'OperatingMemoryModes@odata.count']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_metrics_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_metrics_info.yml
new file mode 100644
index 000000000..2a7498098
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_metrics_info.yml
@@ -0,0 +1,93 @@
+---
+- name: Get Power Supply information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_chassis }}/PowerSubsystem/PowerSupplies?$expand=*($levels=1)"
+ register: power_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Power Supply Metrics ids
+ ansible.builtin.set_fact:
+ power_metrics_ids: "{{ power_result.json.Members | selectattr('Metrics', 'defined') | map(attribute='Metrics') | flatten }}"
+
+- name: Get Power Supply Metrics information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ item['@odata.id'] }}"
+ validate_certs: "{{ validate_certs }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ timeout: "{{ https_timeout }}"
+ force_basic_auth: true
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ loop: "{{ power_metrics_ids }}"
+ register: power_metrics_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Thermal Metrics information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_chassis }}/ThermalSubsystem/ThermalMetrics"
+ validate_certs: "{{ validate_certs }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ timeout: "{{ https_timeout }}"
+ force_basic_auth: true
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: thermal_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Memory information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Memory?$expand=*($levels=1)"
+ validate_certs: "{{ validate_certs }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ timeout: "{{ https_timeout }}"
+ force_basic_auth: true
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: memory_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Memory Metrics ids
+ ansible.builtin.set_fact:
+ memory_metrics_ids: "{{ memory_result.json.Members | selectattr('Metrics', 'defined') | map(attribute='Metrics') | flatten }}"
+
+- name: Get Memory Metrics information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ item['@odata.id'] }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ timeout: "{{ https_timeout }}"
+ force_basic_auth: true
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ loop: "{{ memory_metrics_ids }}"
+ register: memory_metrics_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Power Supply/Thermal/Memory Metrics facts
+ ansible.builtin.set_fact:
+ power_metrics:
+ "{{ power_metrics_result.results | selectattr('json', 'defined') | map(attribute='json') | flatten |
+ ansible.utils.remove_keys(target=['@odata.context', '@odata.type', '@odata.id', 'DataSourceUri']) }}"
+ thermal_metrics:
+ "{{ thermal_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.type', '@odata.id', 'DataSourceUri',
+ 'TemperatureReadingsCelsius@odata.count']) }}"
+ memory_metrics:
+ "{{ memory_metrics_result.results | selectattr('json', 'defined') | map(attribute='json') | flatten |
+ ansible.utils.remove_keys(target=['@odata.context', '@odata.type', '@odata.id', 'DataSourceUri']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_nic_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_nic_info.yml
new file mode 100644
index 000000000..6a022134f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_nic_info.yml
@@ -0,0 +1,12 @@
+---
+- name: Get NIC information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/EthernetInterfaces?$expand=*($levels=1)"
+ register: nic_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set NIC facts
+ ansible.builtin.set_fact:
+ nic:
+ "{{ nic_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'IPv4Addresses@odata.count',
+ 'IPv6AddressPolicyTable@odata.count', 'IPv6Addresses@odata.count', 'IPv6StaticAddresses@odata.count', 'NameServers@odata.count']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pas_sensor_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pas_sensor_info.yml
new file mode 100644
index 000000000..6e58aeca7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pas_sensor_info.yml
@@ -0,0 +1,12 @@
+---
+- name: Get PresenceAndStatusSensor information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Oem/Dell/DellPresenceAndStatusSensors"
+ register: pas_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set PresenceAndStatusSensor facts
+ ansible.builtin.set_fact:
+ "presence_and_status_sensor":
+ "{{ pas_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Assembly',
+ 'Links']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pcie_device_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pcie_device_info.yml
new file mode 100644
index 000000000..f76377b17
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_pcie_device_info.yml
@@ -0,0 +1,10 @@
+---
+- name: Get PCIeDevice information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_chassis }}/PCIeDevices?$expand=*($levels=1)"
+ register: pcie_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set PCIeDevice facts
+ ansible.builtin.set_fact:
+ pcie_device: "{{ pcie_result.json.Members | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Links', '@odata.etag']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_physical_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_physical_info.yml
new file mode 100644
index 000000000..92ad3e454
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_physical_info.yml
@@ -0,0 +1,24 @@
+---
+- name: Get Storage information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Storage"
+ register: disk_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get all storage controller ids.
+ ansible.builtin.set_fact:
+ storage_ids_list: "{{ disk_result.json.Members | map('dict2items') | flatten | map(attribute='value') }}"
+
+- name: Get PhysicalDisk information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ item }}?$expand=*($levels=1)"
+ loop: "{{ storage_ids_list }}"
+ register: result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Physical Disk facts
+ ansible.builtin.set_fact:
+ physical_disk:
+ "{{ result.results | selectattr('json', 'defined') | map(attribute='json') | selectattr('Drives', 'defined') |
+ map(attribute='Drives') | flatten | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type',
+ 'Actions', 'Assembly', 'Links', 'DellDriveSMARTAttributes', 'DellNVMeSMARTAttributes', 'Operations@odata.count']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_power_supply_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_power_supply_info.yml
new file mode 100644
index 000000000..e67fcd882
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_power_supply_info.yml
@@ -0,0 +1,13 @@
+---
+- name: Get PowerSupply information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_chassis }}/PowerSubsystem/PowerSupplies?$expand=*($levels=1)"
+ register: power_supply_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set PowerSupply facts
+ ansible.builtin.set_fact:
+ power_supply:
+ "{{ power_supply_result.json.Members | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.id', '@odata.type', 'ActiveInputVoltage@Redfish.Deprecated', 'OperationalStatus@odata.count',
+ 'RedTypeOfSet@odata.count']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_resource_id.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_resource_id.yml
new file mode 100644
index 000000000..5a1035533
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_resource_id.yml
@@ -0,0 +1,60 @@
+---
+- name: Get system resource api id
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems
+ register: system_api_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+- name: Get first System Id from the system response
+ ansible.builtin.set_fact:
+ api_system: "{{ system_api_result.json.Members[0]['@odata.id'] |
+ default('') }}"
+ computer_system_id: "{{ system_api_result.json.Members[0]['@odata.id'] |
+ split('/') | last | default('System.Embedded.1') }}"
+ when: computer_system_id == ''
+- name: Get all system Ids
+ ansible.builtin.set_fact:
+ system_ids_list: "{{ system_api_result.json.Members | map('dict2items') |
+ flatten | map(attribute='value') }}"
+ when: computer_system_id != ''
+- name: Split system ids from the string
+ ansible.builtin.set_fact:
+ system_ids: '{{ (system_ids | default([])) + ([item | split("/") | last]) }}'
+ with_list: "{{ system_ids_list }}"
+ when: computer_system_id != ''
+- name: Fail when system id is incorrect
+ ansible.builtin.fail:
+ msg: "{{ idrac_gather_facts_invalid_sys_id_message |
+ format(computer_system_id, (system_ids | join(','))) }}"
+ when: computer_system_id != "" and not computer_system_id in system_ids
+- name: Get manager resource api id
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}/redfish/v1/Managers
+ register: manager_api_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+- name: Get first manager resource id from manager response.
+ ansible.builtin.set_fact:
+ api_manager: "{{ manager_api_result.json.Members[0]['@odata.id'] | default('') }}"
+ when: manager_id == ''
+- name: Get all manager resource ids.
+ ansible.builtin.set_fact:
+ manager_ids_list: "{{ manager_api_result.json.Members | map('dict2items') |
+ flatten | map(attribute='value') }}"
+ when: manager_id != ''
+- name: Split manager ids from the string
+ ansible.builtin.set_fact:
+ manager_ids: '{{ (manager_ids | default([])) + ([item | split("/") | last]) }}'
+ with_list: "{{ manager_ids_list }}"
+ when: manager_id != ''
+- name: Fail when manager id is incorrect
+ ansible.builtin.fail:
+ msg: "{{ idrac_gather_facts_invalid_manager_id_message | format(manager_id,
+ (manager_ids | join(','))) }}"
+ when: manager_id != "" and not manager_id in manager_ids
+- name: Get chassis resource api id
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}/redfish/v1/Chassis
+ register: chassis_api_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+- name: Get first chassis resource id from manager response.
+ ansible.builtin.set_fact:
+ api_chassis: "{{ chassis_api_result.json.Members[0]['@odata.id'] | default('') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_secure_boot_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_secure_boot_info.yml
new file mode 100644
index 000000000..20a72cfe2
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_secure_boot_info.yml
@@ -0,0 +1,41 @@
+---
+- name: Get Secure Boot information.
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}{{ api_system
+ }}/SecureBoot/?$expand=*($levels=1)
+ register: secure_boot_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Secure Boot Databases.
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}{{ api_system
+ }}/SecureBoot/SecureBootDatabases?$expand=*($levels=1)
+ register: secure_boot_db_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get Secureboot db certificates information.
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}{{
+ sec_boot_db_item['Certificates']['@odata.id'] }}?$expand=*($levels=1)
+ loop: "{{ secure_boot_db_result.json.Members }}"
+ loop_control:
+ loop_var: sec_boot_db_item
+ register: secure_boot_results
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Combine certificates with corresponding db information.
+ ansible.builtin.set_fact:
+ interim_secure_boot: "{{ interim_secure_boot | default([]) +
+ [sec_boot_cert['sec_boot_db_item'] | combine({'Certificates':
+ sec_boot_cert['json']['Members']})] }}"
+ loop: "{{ secure_boot_results.results }}"
+ loop_control:
+ loop_var: sec_boot_cert
+ no_log: true
+
+- name: Combine the secure boot database and certificates into secure boot.
+ ansible.builtin.set_fact:
+ secure_boot: '{{ secure_boot_result.json | combine({"SecureBootDatabases":
+ interim_secure_boot}) |
+ ansible.utils.remove_keys(target=["^.*@odata\..*$"],
+ matching_parameter="regex") }}'
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_system_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_system_info.yml
new file mode 100644
index 000000000..953fde59d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_system_info.yml
@@ -0,0 +1,19 @@
+---
+- name: Get system information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}"
+ register: system_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get operating system information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Managers/{{
+ computer_system_id }}/Attributes?$select=ServerOS.*"
+ register: os_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set system facts
+ ansible.builtin.set_fact:
+ system:
+ "{{ system_result.json.Oem.Dell.DellSystem | combine(os_result.json.Attributes) |
+ ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_virtual_disk_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_virtual_disk_info.yml
new file mode 100644
index 000000000..6d913a477
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_virtual_disk_info.yml
@@ -0,0 +1,25 @@
+---
+- name: Get Storage information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_system }}/Storage"
+ register: virtual_disk_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Get all storage controller ids.
+ ansible.builtin.set_fact:
+ storage_ids_list: "{{ virtual_disk_result.json.Members | map('dict2items') | flatten | map(attribute='value') | default('') }}"
+
+- name: Get Virtual Disk information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ item }}/Volumes?$expand=*($levels=1)"
+ loop: "{{ storage_ids_list }}"
+ register: result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Virtual Disk facts
+ ansible.builtin.set_fact:
+ virtual_disk:
+ "{{ result.results | selectattr('json', 'defined') | map(attribute='json') | selectattr('Members', 'defined') |
+ map(attribute='Members') | flatten | ansible.utils.remove_keys(target=['@odata.context', '@odata.type',
+ '@odata.id', 'Actions', 'EncryptionTypes@odata.count', 'Identifiers@odata.count', 'Links',
+ 'Operations@odata.count', 'DellVirtualDisk', 'DellVirtualDisk@Redfish.Deprecated']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_voltage_info.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_voltage_info.yml
new file mode 100644
index 000000000..a1b9d4e91
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/get_voltage_info.yml
@@ -0,0 +1,12 @@
+---
+- name: Get Sensor Voltage information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ api_chassis }}/Power#/Voltages"
+ register: voltage_result
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+- name: Set Sensor Voltage facts
+ ansible.builtin.set_fact:
+ "voltages":
+ "{{ voltage_result.json.Voltages | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.id', '@odata.type']) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/main.yml
new file mode 100644
index 000000000..b67ed56f0
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tasks/main.yml
@@ -0,0 +1,81 @@
+---
+- name: IDRAC Gather facts
+ module_defaults:
+ ansible.builtin.uri:
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ timeout: "{{ https_timeout }}"
+ force_basic_auth: true
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ block:
+ - name: Check whether atleast one of 'IDRAC_USERNAME' or username is provided
+ ansible.builtin.fail:
+ msg: Ensure the value for environment variable 'IDRAC_USERNAME'
+ or the argument 'username' is set.
+ when: username is not defined and not lookup('env', 'IDRAC_USERNAME')
+
+ - name: Check whether atleast one of 'IDRAC_PASSWORD' or password is provided
+ ansible.builtin.fail:
+ msg: Ensure the value for environment variable 'IDRAC_PASSWORD'
+ or the argument 'password' is set.
+ when: password is not defined and not lookup('env', 'IDRAC_PASSWORD')
+
+ - name: Set default facts
+ ansible.builtin.set_fact:
+ idrac: {}
+ system: {}
+ bios: {}
+ controller: []
+ cpu: []
+ enclosure: []
+ enclosure_emm: []
+ fan: []
+ firmware: []
+ hostnic: []
+ license: []
+ memory: []
+ nic: []
+ backplane: []
+ power_supply: []
+ presence_and_status_sensor: []
+ sensor_battery: {}
+ intrusion_sensor: {}
+ voltages: []
+ virtual_disk: []
+ pcie_device: {}
+ physical_disk: []
+ power_metrics: []
+ thermal_metrics: []
+ memory_metrics: []
+ secure_boot: {}
+
+ - name: Get connection
+ ansible.builtin.uri:
+ url: https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems
+ register: idrac_gather_facts_connection
+ delegate_to: "{{ idrac_gather_facts_delegate }}"
+
+ - name: Fail when hostname or certificate is incorrect or invalid.
+ ansible.builtin.fail:
+ msg: "{{ idrac_gather_facts_connection.msg }}"
+ when: idrac_gather_facts_connection.status == -1
+
+ - name: Fail when credentials are incorrect or invalid.
+ ansible.builtin.fail:
+ msg: The authentication credentials included with this request
+ are missing or invalid.
+ when: idrac_gather_facts_connection.status == 401
+
+ - name: Get System, Manager and Chassis resource id.
+ ansible.builtin.include_tasks: get_resource_id.yml
+
+ - name: Get target facts in loop
+ ansible.builtin.include_tasks: "{{
+ idrac_gather_facts_target_yml_map[item] }}"
+ loop: "{{ target }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/backplane_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/backplane_assert.yml
new file mode 100644
index 000000000..a4562f9e0
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/backplane_assert.yml
@@ -0,0 +1,39 @@
+- name: Get PCIeSSDBackPlanes information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/Chassis/Oem/Dell/DellPCIeSSDBackPlanes/{{ backplane_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: backplane_result
+ no_log: true
+
+- name: Set backplane facts
+ ansible.builtin.set_fact:
+ api_response: "{{ backplane_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ backplane_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a Diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: backplane_data[item]}) }}"
+ loop: "{{ backplane_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - backplane_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/controller_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/controller_assert.yml
new file mode 100644
index 000000000..277e524a2
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/controller_assert.yml
@@ -0,0 +1,70 @@
+---
+- name: Fetching Controller info
+ ansible.builtin.uri: &uri_params
+ url: "https://{{ hostname }}{{ api_system }}/Storage"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: idrac_gather_facts_storage_entity
+ no_log: true
+
+- name: Get storage entities
+ ansible.builtin.set_fact:
+ collected_storage_entity:
+ "{{ (collected_storage_entity | default([])) + [item['@odata.id']] }}"
+ loop: "{{ idrac_gather_facts_storage_entity.json.Members }}"
+
+- name: Get Controllers URL information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ item }}"
+ <<: *uri_params
+ loop: "{{ collected_storage_entity }}"
+ register: idrac_gather_facts_controllers_url
+
+- name: Pick Controllers key value in one list
+ ansible.builtin.set_fact:
+ controllers_list:
+ "{{ controllers_list | default([]) +
+ [item.json.Controllers | default(omit)] }}"
+ loop: "{{ idrac_gather_facts_controllers_url.results }}"
+
+- name: Select list of controller values from dictionary
+ ansible.builtin.set_fact:
+ collected_values:
+ "{{ (collected_values | default([])) +
+ [item['@odata.id'] | default(omit)] }}"
+ loop: "{{ controllers_list }}"
+
+- name: Get Controllers information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ item }}?$expand=*($levels=1)"
+ <<: *uri_params
+ loop: "{{ collected_values | reject('match', '__omit_place_holder__.*') }}"
+ register: idrac_gather_facts_result
+
+- name: Set All Controllers facts
+ ansible.builtin.set_fact:
+ api_response:
+ "{{ idrac_gather_facts_result.results | selectattr('json', 'defined') |
+ map(attribute='json') |
+ selectattr('Members', 'defined') |
+ map(attribute='Members') | flatten |
+ ansible.utils.remove_keys(target=['^.*@odata.*$'],
+ matching_parameter='regex') }}"
+
+- name: Check whether output differs
+ ansible.builtin.set_fact:
+ result_diff: "{{ controller | symmetric_difference(api_response) }}"
+
+- name: Assert the differences in List
+ ansible.builtin.assert:
+ that:
+ - "{{ (result_diff | length) == 0 }}"
+ fail_msg: "The response from the role does not match"
+ success_msg: "The response from the role matches"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/cpu_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/cpu_assert.yml
new file mode 100644
index 000000000..8ff78d62d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/cpu_assert.yml
@@ -0,0 +1,40 @@
+---
+- name: Fetching CPU information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Processors/{{ cpu_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: cpu_result
+ no_log: true
+
+- name: Set CPU facts
+ ansible.builtin.set_fact:
+ api_response: "{{ cpu_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Assembly', 'Links']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ cpu_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: cpu_data[item]}) }}"
+ loop: "{{ cpu_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - cpu_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosure_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosure_assert.yml
new file mode 100644
index 000000000..49f457708
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosure_assert.yml
@@ -0,0 +1,39 @@
+- name: Fetching Enclosure info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/Chassis/Oem/Dell/DellEnclosures/{{ enclosure_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: enclosure_result
+ no_log: true
+
+- name: Set enclosure facts
+ ansible.builtin.set_fact:
+ api_response: "{{ enclosure_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Links', 'Description']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ enclosure_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: enclosure_data[item]}) }}"
+ loop: "{{ enclosure_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - enclosure_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosureemm_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosureemm_assert.yml
new file mode 100644
index 000000000..7919c984b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/enclosureemm_assert.yml
@@ -0,0 +1,39 @@
+- name: Fetching EnclosureEMM info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/Chassis/Oem/Dell/DellEnclosureEMM/{{ enclosureemm_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: enclosureemm_result
+ no_log: true
+
+- name: Set enclosureemm facts
+ ansible.builtin.set_fact:
+ api_response: "{{ enclosureemm_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Description', 'Links']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ enclosureemm_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: enclosureemm_data[item]}) }}"
+ loop: "{{ enclosureemm_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - enclosureemm_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/fan_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/fan_assert.yml
new file mode 100644
index 000000000..b3f50e760
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/fan_assert.yml
@@ -0,0 +1,39 @@
+- name: Fetching Fan info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}/ThermalSubsystem/Fans/{{ fan_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: fan_result
+ no_log: true
+
+- name: Set fan facts
+ ansible.builtin.set_fact:
+ api_response: "{{ fan_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ fan_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: fan_data[item]}) }}"
+ loop: "{{ fan_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - fan_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/firmware_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/firmware_assert.yml
new file mode 100644
index 000000000..49168f07e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/firmware_assert.yml
@@ -0,0 +1,40 @@
+- name: Fetching Firmware info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/UpdateService/FirmwareInventory/{{ firmware_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: firmware_result
+ no_log: true
+
+- name: Set firmware facts
+ ansible.builtin.set_fact:
+ api_response: "{{ firmware_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Classifications@odata.count',
+ 'IdentityInfoType@odata.count', 'IdentityInfoValue@odata.count']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ firmware_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: firmware_data[item]}) }}"
+ loop: "{{ firmware_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - firmware_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/hostnic_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/hostnic_assert.yml
new file mode 100644
index 000000000..23f2648d5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/hostnic_assert.yml
@@ -0,0 +1,40 @@
+- name: Fetching HostNIC info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_manager }}/HostInterfaces/{{ hostnic_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: hostnic_result
+ no_log: true
+
+- name: Set hostnic facts
+ ansible.builtin.set_fact:
+ api_response: "{{ hostnic_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'HostEthernetInterfaces',
+ 'ManagerEthernetInterface']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ hostnic_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: hostnic_data[item]}) }}"
+ loop: "{{ hostnic_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - hostnic_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/lc_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/lc_assert.yml
new file mode 100644
index 000000000..df83810d6
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/lc_assert.yml
@@ -0,0 +1,28 @@
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ idrac_lc_attributes: "{{ idrac.lifecycle_controller_attributes }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ api_idrac_lc_attributes: "{{ api_idrac.api_lifecycle_controller_attributes }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ idrac_lc_attributes.keys() | list | symmetric_difference((api_idrac_lc_attributes.keys() | list)) }}"
+
+- name: Set a Diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: idrac_lc_attributes[item]}) }}"
+ loop: "{{ idrac_lc_attributes.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - idrac_lc_attributes[item] != api_idrac_lc_attributes[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/license_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/license_assert.yml
new file mode 100644
index 000000000..93c76ac69
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/license_assert.yml
@@ -0,0 +1,39 @@
+- name: Get license information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/LicenseService/Licenses/{{ license_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: license_result
+ no_log: true
+
+- name: Set license facts
+ ansible.builtin.set_fact:
+ api_response: "{{ license_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ license_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: license_data[item]}) }}"
+ loop: "{{ license_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - license_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/manager_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/manager_assert.yml
new file mode 100644
index 000000000..6e62062a5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/manager_assert.yml
@@ -0,0 +1,28 @@
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ idrac_manager_attributes: "{{ idrac.manager_attributes }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ api_idrac_manager_attributes: "{{ api_idrac.api_manager_attributes }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ idrac_manager_attributes.keys() | list | symmetric_difference((api_idrac_manager_attributes.keys() | list)) }}"
+
+- name: Set a Diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: idrac_manager_attributes[item]}) }}"
+ loop: "{{ idrac_manager_attributes.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - idrac_manager_attributes[item] != api_idrac_manager_attributes[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/memory_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/memory_assert.yml
new file mode 100644
index 000000000..08b56689b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/memory_assert.yml
@@ -0,0 +1,40 @@
+- name: Fetching memory info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Memory/{{ memory_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: memory_result
+ no_log: true
+
+- name: Set memory facts
+ ansible.builtin.set_fact:
+ api_response: "{{ memory_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'AllowedSpeedsMHz@odata.count',
+ 'CPUAffinity@odata.count', 'Processors@odata.count', 'MaxTDPMilliWatts@odata.count', 'OperatingMemoryModes@odata.count']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ memory_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: memory_data[item]}) }}"
+ loop: "{{ memory_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - memory_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/mmetrics_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/mmetrics_assert.yml
new file mode 100644
index 000000000..1cc040b73
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/mmetrics_assert.yml
@@ -0,0 +1,38 @@
+- name: Get Memory information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Memory/{{ memory_data.Id }}/MemoryMetrics"
+ validate_certs: "{{ validate_certs }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: response_memory_metrics
+ no_log: true
+
+- name: Set Memory Metrics facts
+ ansible.builtin.set_fact:
+ api_memory_metrics: "{{ response_memory_metrics.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.type', '@odata.id', 'DataSourceUri']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ memory_data.keys() | list | symmetric_difference((api_memory_metrics.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: memory_data[item]}) }}"
+ loop: "{{ memory_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - memory_data[item] != api_memory_metrics[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/nic_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/nic_assert.yml
new file mode 100644
index 000000000..3c334bd2a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/nic_assert.yml
@@ -0,0 +1,40 @@
+- name: Get NIC information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/EthernetInterfaces/{{ nic_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: nic_result
+ no_log: true
+
+- name: Set nic facts
+ ansible.builtin.set_fact:
+ api_response: "{{ nic_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'IPv4Addresses@odata.count',
+ 'IPv6AddressPolicyTable@odata.count', 'IPv6Addresses@odata.count', 'IPv6StaticAddresses@odata.count', 'NameServers@odata.count']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ nic_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: nic_data[item]}) }}"
+ loop: "{{ nic_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - nic_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/passensor_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/passensor_assert.yml
new file mode 100644
index 000000000..6931c9204
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/passensor_assert.yml
@@ -0,0 +1,39 @@
+- name: Fetching Presence and Status Sensor info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Oem/Dell/DellPresenceAndStatusSensors/{{ passensor_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ no_log: true
+ register: passensor_result
+
+- name: Set presence and status sensor facts
+ ansible.builtin.set_fact:
+ api_response: "{{ passensor_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Assembly', 'Links']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ passensor_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: passensor_data[item]}) }}"
+ loop: "{{ passensor_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - passensor_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/pciedevice_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/pciedevice_assert.yml
new file mode 100644
index 000000000..de762c302
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/pciedevice_assert.yml
@@ -0,0 +1,39 @@
+- name: Fetching PCIeDevice info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}/PCIeDevices/{{ pci_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ no_log: true
+ register: pci_result
+
+- name: Set pcie device facts
+ ansible.builtin.set_fact:
+ api_response: "{{ pci_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type', 'Links', '@odata.etag']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ pci_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: pci_data[item]}) }}"
+ loop: "{{ pci_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - pci_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/physicaldisk_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/physicaldisk_assert.yml
new file mode 100644
index 000000000..76ec6624f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/physicaldisk_assert.yml
@@ -0,0 +1,45 @@
+---
+- name: Get controller id
+ ansible.builtin.set_fact:
+ ctrl_id: "{{ pd_data.Id | split(':') | last }}"
+
+- name: Get Storage information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Storage/{{ ctrl_id }}/Drives/{{ pd_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ no_log: true
+ register: disk_result
+
+- name: Filter Physical Disk data
+ ansible.builtin.set_fact:
+ api_response: "{{ disk_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.id', '@odata.type',
+ 'Actions', 'Assembly', 'Links', 'DellDriveSMARTAttributes', 'DellNVMeSMARTAttributes', 'Operations@odata.count']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ pd_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a Diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: pd_data[item]}) }}"
+ loop: "{{ pd_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - pd_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/powersupply_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/powersupply_assert.yml
new file mode 100644
index 000000000..ddb77ce04
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/powersupply_assert.yml
@@ -0,0 +1,42 @@
+- name: Fetching Power Supply info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}/PowerSubsystem/PowerSupplies/{{ powersupply_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: powersupply_result
+ no_log: true
+
+- name: Set powersupply facts
+ ansible.builtin.set_fact:
+ api_response:
+ "{{ powersupply_result.json | ansible.utils.remove_keys(target=['@odata.context',
+ '@odata.id', '@odata.type', 'ActiveInputVoltage@Redfish.Deprecated', 'OperationalStatus@odata.count',
+ 'RedTypeOfSet@odata.count']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ powersupply_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: powersupply_data[item]}) }}"
+ loop: "{{ powersupply_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - powersupply_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/psmetrics_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/psmetrics_assert.yml
new file mode 100644
index 000000000..ae53db89d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/psmetrics_assert.yml
@@ -0,0 +1,29 @@
+- name: Get Power information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_chassis }}//PowerSubsystem/PowerSupplies/{{ psu_ids[index] }}/Metrics"
+ validate_certs: "{{ validate_certs }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: response_power_metrics
+ no_log: true
+
+- name: Set Power Supply Metrics facts
+ ansible.builtin.set_fact:
+ api_power_metrics: "{{ response_power_metrics.json |
+ ansible.utils.remove_keys(target=['@odata.context', '@odata.type', '@odata.id', 'DataSourceUri']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ power_data.keys() | list | symmetric_difference((api_power_metrics.keys() | list)) }}"
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/secureboot_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/secureboot_assert.yml
new file mode 100644
index 000000000..9df2660c1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/secureboot_assert.yml
@@ -0,0 +1,62 @@
+---
+- name: Fetching Secureboot info
+ ansible.builtin.uri: &uri_params
+ url: "https://{{ hostname }}{{ api_system
+ }}/SecureBoot/?$expand=*($levels=1)"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ register: idrac_gather_facts_secureboot_details
+
+- name: Fetching Secureboot database info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system
+ }}/SecureBoot/SecureBootDatabases?$expand=*($levels=1)"
+ <<: *uri_params
+ register: idrac_gather_facts_secureboot_database_details
+
+- name: Fetching Secureboot database certificates info
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{
+ sec_boot_db_item['Certificates']['@odata.id'] }}
+ ?$expand=*($levels=1)"
+ <<: *uri_params
+ loop: "{{ idrac_gather_facts_secureboot_database_details.json.Members }}"
+ loop_control:
+ loop_var: sec_boot_db_item
+ register: idrac_gather_facts_secure_boot_results
+
+- name: Combine certificates with corresponding database information.
+ ansible.builtin.set_fact:
+ interim_secure_boot: "{{ interim_secure_boot | default([]) +
+ [sec_boot_cert['sec_boot_db_item'] | combine({'Certificates':
+ sec_boot_cert['json']['Members']})] }}"
+ loop: "{{ secure_boot_results.results }}"
+ loop_control:
+ loop_var: sec_boot_cert
+ no_log: true
+
+- name: Combine the secure boot database and certificates into secure boot.
+ ansible.builtin.set_fact:
+ api_response: '{{ idrac_gather_facts_secureboot_details.json |
+ combine({"SecureBootDatabases":
+ interim_secure_boot}) |
+ ansible.utils.remove_keys(target=["^.*@odata\..*$"],
+ matching_parameter="regex") }}'
+
+- name: Check whether output differs
+ ansible.builtin.set_fact:
+ result_diff: "{{ secure_boot | symmetric_difference(api_response) }}"
+
+- name: Assert the differences in List
+ ansible.builtin.assert:
+ fail_msg: "The response from the role does not match"
+ success_msg: "The response from the role matches"
+ that:
+ - "{{ (result_diff | length) == 0 }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/sensorsvoltage_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/sensorsvoltage_assert.yml
new file mode 100644
index 000000000..0e6e2a0da
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/sensorsvoltage_assert.yml
@@ -0,0 +1,20 @@
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ sensorsvoltage_data.keys() | list | symmetric_difference((api_response[index].keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: sensorsvoltage_data[item]}) }}"
+ loop: "{{ sensorsvoltage_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - sensorsvoltage_data[item] != api_response[index][item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/system_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/system_assert.yml
new file mode 100644
index 000000000..5376d1d42
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/system_assert.yml
@@ -0,0 +1,28 @@
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ idrac_system_attributes: "{{ idrac.system_attributes }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ api_idrac_system_attributes: "{{ api_idrac.api_system_attributes }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ idrac_system_attributes.keys() | list | symmetric_difference((api_idrac_system_attributes.keys() | list)) }}"
+
+- name: Set a Diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: idrac_system_attributes[item]}) }}"
+ loop: "{{ idrac_system_attributes.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - idrac_system_attributes[item] != api_idrac_system_attributes[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/tmetrics_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/tmetrics_assert.yml
new file mode 100644
index 000000000..25a8229cf
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/tmetrics_assert.yml
@@ -0,0 +1,20 @@
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ thermal_metrics.keys() | list | symmetric_difference((api_thermal_metrics.keys() | list)) }}"
+
+- name: Set a diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: thermal_metrics[item]}) }}"
+ loop: "{{ thermal_metrics.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - thermal_metrics[item] != api_thermal_metrics[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/virtualdisk_assert.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/virtualdisk_assert.yml
new file mode 100644
index 000000000..6622031c7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/asserts/virtualdisk_assert.yml
@@ -0,0 +1,45 @@
+---
+- name: Get controller id
+ ansible.builtin.set_fact:
+ ctrl_id: "{{ virtualdisk_data.Id | split(':') | last }}"
+
+- name: Get Storage information.
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}{{ api_system }}/Storage/{{ ctrl_id }}/Volumes/{{ virtualdisk_data.Id }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: "{{ idrac_gather_facts_uri_method }}"
+ user: "{{ username }}"
+ password: "{{ password }}"
+ headers: "{{ idrac_gather_facts_uri_headers }}"
+ body_format: "{{ idrac_gather_facts_uri_body_format }}"
+ status_code: "{{ idrac_gather_facts_uri_status_code }}"
+ return_content: "{{ idrac_gather_facts_uri_return_content }}"
+ no_log: true
+ register: virtualdisk_result
+
+- name: Filter Virtual Disk data
+ ansible.builtin.set_fact:
+ api_response: "{{ virtualdisk_result.json | ansible.utils.remove_keys(target=['@odata.context', '@odata.type', '@odata.id', 'Actions',
+ 'EncryptionTypes@odata.count', 'Identifiers@odata.count', 'Links', 'Operations@odata.count', 'DellVirtualDisk', 'DellVirtualDisk@Redfish.Deprecated']) }}"
+
+- name: Set the keys diff
+ ansible.builtin.set_fact:
+ diff_keys: "{{ virtualdisk_data.keys() | list | symmetric_difference((api_response.keys() | list)) }}"
+
+- name: Set a Diff of dict
+ ansible.builtin.set_fact:
+ diff_data: "{{ diff_data | combine({item: virtualdisk_data[item]}) }}"
+ loop: "{{ virtualdisk_data.keys() }}"
+ when:
+ - diff_keys | length == 0
+ - virtualdisk_data[item] != api_response[item]
+ - item not in exclude_keys
+
+- name: Assert the difference in Keys
+ ansible.builtin.assert:
+ that:
+ - "{{ (diff_keys | length) == 0 }}"
+ - "{{ (diff_data | length) == 0 }}"
+ fail_msg: "The response from the role does not match | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
+ success_msg: "The response from the role matches | Diff Keys : {{ diff_keys }} Diff Data : {{ diff_data }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/test.yml
new file mode 100644
index 000000000..f9e315314
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Call Role Gather Facts
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_gather_facts
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/vars/main.yml
new file mode 100644
index 000000000..efe6c061f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_gather_facts/vars/main.yml
@@ -0,0 +1,46 @@
+---
+# vars file for idrac_gather_facts
+idrac_gather_facts_invalid_sys_id_message: "Invalid computer system id : %s, valid values are %s"
+idrac_gather_facts_invalid_manager_id_message: "Invalid computer manager id : %s, valid values are %s"
+
+idrac_gather_facts_uri_method: "GET"
+idrac_gather_facts_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+idrac_gather_facts_uri_body_format: "json"
+idrac_gather_facts_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+idrac_gather_facts_uri_return_content: true
+idrac_gather_facts_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+
+# Mapping of target facts to yml file
+idrac_gather_facts_target_yml_map:
+ IDRAC: get_attributes_info.yml
+ System: get_system_info.yml
+ BIOS: get_bios_info.yml
+ Controller: get_controller_info.yml
+ CPU: get_cpu_info.yml
+ Enclosure: get_enclosure_info.yml
+ EnclosureEMM: get_enclosure_emm_info.yml
+ Fan: get_fan_info.yml
+ Firmware: get_firmware_info.yml
+ HostNIC: get_host_nic_info.yml
+ License: get_license_info.yml
+ Memory: get_memory_info.yml
+ NIC: get_nic_info.yml
+ PCIeSSDBackPlane: get_backplane_info.yml
+ PowerSupply: get_power_supply_info.yml
+ PresenceAndStatusSensor: get_pas_sensor_info.yml
+ Sensors_Battery: get_battery_info.yml
+ Sensors_Intrusion: get_intrusion_info.yml
+ Sensors_Voltage: get_voltage_info.yml
+ VirtualDisk: get_virtual_disk_info.yml
+ PCIeDevice: get_pcie_device_info.yml
+ PhysicalDisk: get_physical_info.yml
+ SystemMetrics: get_metrics_info.yml
+ SecureBoot: get_secure_boot_info.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/README.md
new file mode 100644
index 000000000..70164206b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/README.md
@@ -0,0 +1,393 @@
+# idrac_import_server_config_profile
+
+Role to import the Server Configuration Profile (SCP) from the iDRAC to a network share (CIFS, NFS, HTTP, HTTPS) or a local path.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td> The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>share_parameters</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>Network share parameters.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;share_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Network share or local path.<br>- CIFS, NFS, HTTP, and HTTPS network share types are supported.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scp_file</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Name of the server configuration profile (SCP) file.</br>- The default format `idrac_ip_YYMMDD_HHMMSS_scp` is used if this option is not specified.</br>- I(export_format) is used if the valid extension file is not provided.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;share_user</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>Network share user in the format 'user@domain' or 'domain\\user' if user is part of a domain else 'user'. This option is mandatory for CIFS Network Share..</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;share_password</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>Network share user password. This option is mandatory for CIFS Network Share.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_support</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Proxy to be enabled or disabled.</br>- I(proxy_support) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_type</td>
+ <td>false</td>
+ <td>http</td>
+ <td>http, socks4</td>
+ <td>str</td>
+ <td>- C(http) to select HTTP type proxy.</br>- C(socks4) to select SOCKS4 type proxy.</br>- I(proxy_type) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_server</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td> - I(proxy_server) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).</br>- I(proxy_server) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_port</td>
+ <td>false</td>
+ <td>80</td>
+ <td></td>
+ <td>str</td>
+ <td>- Proxy port to authenticate.</br> - I(proxy_port) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).</br>- I(proxy_port) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_username</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Proxy username to authenticate.</br>- I(proxy_username) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_password</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Proxy password to authenticate.</br>- I(proxy_password) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ignore_certificate_warning</td>
+ <td>false</td>
+ <td>ignore</td>
+ <td>ignore, showerror</td>
+ <td>str</td>
+ <td>- If C(ignore), it ignores the certificate warnings.</br>- If C(showerror), it shows the certificate warnings.</br>
+ - I(ignore_certificate_warning) is considered only when I(share_name) is of type HTTPS and is supported only on iDRAC9.</td>
+ </tr>
+ <tr>
+ <td>target</td>
+ <td>false</td>
+ <td>['ALL']</td>
+ <td>'ALL', 'IDRAC', 'BIOS', 'NIC', 'RAID'</td>
+ <td>str</td>
+ <td>- If C(ALL), this module exports or imports all components configurations from SCP file.<br>- If C(IDRAC), this module exports or imports iDRAC configuration from SCP file.<br>- If C(BIOS), this module exports or imports BIOS configuration from SCP file.<br>- If C(NIC), this module exports or imports NIC configuration from SCP file.<br>- If C(RAID), this module exports or imports RAID configuration from SCP file.</br>- When I(command) is C(export) or C(import) I(target) with multiple components is supported only on iDRAC9 with firmware 6.10.00.00 and above.</td>
+ </tr>
+ <tr>
+ <td>import_buffer</td>
+ <td>false</td>
+ <td></td>
+ <td>'Enabled', 'Disabled'</td>
+ <td>str</td>
+ <td> - SCP content buffer.<br>
+ - This is mutually exclusive with share_parameters.scp_file.
+ </td>
+ </tr>
+ <tr>
+ <td>end_host_power_state</td>
+ <td>false</td>
+ <td>'On'</td>
+ <td>'On', 'Off'</td>
+ <td>str</td>
+ <td> Host power state after import of server configuration profile.</td>
+ </tr>
+ <tr>
+ <td>shutdown_type</td>
+ <td>false</td>
+ <td>'Graceful'</td>
+ <td>'Graceful', 'Forced', 'NoReboot'</td>
+ <td>str</td>
+ <td> Server shutdown type.</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_import_server_config_profile_out</td>
+ <td>{
+ "changed": false,
+ "msg": "Successfully imported the Server Configuration Profile.",
+ "scp_status": {
+ "CompletionTime": "2023-02-21T04:12:37",
+ "Description": "Job Instance",
+ "EndTime": null,
+ "Id": "JID_774927528227",
+ "JobState": "Completed",
+ "JobType": "ImportConfiguration",
+ "Message": "No changes were applied since the current component configuration matched the requested configuration.",
+ "MessageArgs": [],
+ "MessageId": "IDRAC.2.8.SYS069",
+ "Name": "Configure: Import Server Configuration Profile",
+ "PercentComplete": 100,
+ "StartTime": "TIME_NOW",
+ "TargetSettingsURI": null,
+ "TaskStatus": "OK",
+ "file": ".\\192.1.2.1_2023221_5549_scp.xml",
+ "retval": true
+ }
+}</td>
+ <td>Module output of the Server Configuration Job</td>
+ </tr>
+ </tbody>
+</table>
+
+## Examples
+-----
+
+```
+- name: Importing SCP from local path with all components
+ ansible.builtin.import_role:
+ name: idrac_import_server_config_profile
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ share_parameters:
+ share_name: "/root/tmp"
+ scp_file: "file.xml"
+```
+```
+- name: Importing SCP from NFS with iDRAC components
+ ansible.builtin.import_role:
+ name: idrac_import_server_config_profile
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['IDRAC']
+ share_parameters:
+ share_name: "191.2.1.1:/nfs"
+ scp_file: "file.json"
+```
+```
+- name: Importing SCP from CIFS with BIOS components
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['BIOS']
+ share_parameters:
+ share_name: "\\\\191.1.1.1\\cifs"
+ share_user: "username"
+ share_password: "password"
+ scp_file: "file.xml"
+```
+```
+- name: Importing SCP from HTTPS with RAID components
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['RAID']
+ share_parameters:
+ share_name: "https://192.1.1.1/share"
+ share_user: "username"
+ share_password: "password"
+ scp_file: "filename.json"
+```
+```
+- name: "Importing SCP from HTTP with NIC components"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['NIC']
+ share_parameters:
+ share_name: "http://192.1.1.1/share"
+ share_user: "username"
+ share_password: "password"
+ scp_file: "filename.xml"
+```
+```
+- name: "Importing SCP using import buffer with NIC components"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['NIC']
+ import_buffer: "<SystemConfiguration><Component FQDD='iDRAC.Embedded.1'><Attribute Name='IPMILan.1#Enable'> Disabled</Attribute></Component></SystemConfiguration>"
+```
+```
+- name: "Importing SCP from HTTP with NIC components using proxy"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ target: ['NIC']
+ share_parameters:
+ share_name: "http://192.1.1.1/share"
+ share_user: "username"
+ share_password: "password"
+ scp_file: "filename.xml"
+ proxy_support: true
+ proxy_server: 192.168.0.6
+ proxy_port: 8080
+ proxy_type: socks4
+```
+```
+- name: Import SCP
+ hosts: idrac
+ roles:
+ - role: idrac_import_server_config_profile
+```
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Abhishek Sinha (Abhishek.Sinha10@Dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/defaults/main.yml
new file mode 100644
index 000000000..79e251f31
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/defaults/main.yml
@@ -0,0 +1,15 @@
+---
+# defaults file for idrac_import_server_config_profile
+
+https_port: 443
+validate_certs: true
+https_timeout: 30
+end_host_power_state: 'On'
+shutdown_type: Graceful
+share_parameters:
+ proxy_support: false
+ proxy_type: http
+ proxy_port: "80"
+ ignore_certificate_warning: ignore
+target:
+ - 'ALL'
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/handlers/main.yml
new file mode 100644
index 000000000..6a96ab10f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_import_server_config_profile
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/argument_specs.yml
new file mode 100644
index 000000000..3c61a094e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/argument_specs.yml
@@ -0,0 +1,138 @@
+---
+argument_specs:
+ main:
+ version_added: "7.4.0"
+ short_description: Import iDRAC Server Configuration Profile (SCP)
+ description:
+ - The role performs Import operation of Server Configuration Profile.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ username:
+ type: str
+ description: iDRAC username.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ share_parameters:
+ description: Network share parameters.
+ type: dict
+ options:
+ share_name:
+ description:
+ - Network share or local path.
+ - CIFS, NFS, HTTP, and HTTPS network share types are supported.
+ - I(share_name) is mutually exclusive with I(import_buffer).
+ type: str
+ scp_file:
+ description:
+ - Name of the server configuration profile (SCP) file.
+ - This option is mandatory if I(command) is C(import).
+ - The default format <idrac_ip>_YYMMDD_HHMMSS_scp is used if this option is not specified for C(import).
+ - I(export_format) is used if the valid extension file is not provided for C(export).
+ type: str
+ share_user:
+ description: Network share user in the format 'user@domain' or 'domain\\user' if user is
+ part of a domain else 'user'. This option is mandatory for CIFS Network Share.
+ type: str
+ share_password:
+ description: Network share user password. This option is mandatory for CIFS Network Share.
+ type: str
+ proxy_support:
+ description:
+ - Proxy to be enabled or disabled.
+ - I(proxy_support) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: bool
+ default: false
+ proxy_type:
+ description:
+ - C(http) to select HTTP type proxy.
+ - C(socks4) to select SOCKS4 type proxy.
+ - I(proxy_type) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ choices: [http, socks4]
+ default: http
+ proxy_server:
+ description:
+ - I(proxy_server) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).
+ - I(proxy_server) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ proxy_port:
+ description:
+ - Proxy port to authenticate.
+ - I(proxy_port) is required when I(share_name) is of type HTTPS or HTTP and I(proxy_support) is C(true).
+ - I(proxy_port) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: int
+ default: 80
+ proxy_username:
+ description:
+ - Proxy username to authenticate.
+ - I(proxy_username) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ proxy_password:
+ description:
+ - Proxy password to authenticate.
+ - I(proxy_password) is considered only when I(share_name) is of type HTTP or HTTPS and is supported only on iDRAC9.
+ type: str
+ ignore_certificate_warning:
+ description:
+ - If C(ignore), it ignores the certificate warnings.
+ - If C(showerror), it shows the certificate warnings.
+ - I(ignore_certificate_warning) is considered only when I(share_name) is of type HTTPS and is
+ supported only on iDRAC9.
+ type: str
+ choices: [ignore, showerror]
+ default: ignore
+ target:
+ description:
+ - If C(ALL), this module exports or imports all components configurations from SCP file.
+ - If C(IDRAC), this module exports or imports iDRAC configuration from SCP file.
+ - If C(BIOS), this module exports or imports BIOS configuration from SCP file.
+ - If C(NIC), this module exports or imports NIC configuration from SCP file.
+ - If C(RAID), this module exports or imports RAID configuration from SCP file.
+ choices: ['ALL', 'IDRAC', 'BIOS', 'NIC', 'RAID']
+ default: ['ALL']
+ type: list
+ import_buffer:
+ description:
+ - Used to import the buffer input of xml or json into the iDRAC.
+ - This option is applicable when I(command) is C(import) and C(preview).
+ - I(import_buffer) is mutually exclusive with I(share_name).
+ type: str
+ shutdown_type:
+ description:
+ - This option is applicable for C(import) command.
+ - If C(Graceful), the job gracefully shuts down the operating system and turns off the server.
+ - If C(Forced), it forcefully shuts down the server.
+ - If C(NoReboot), the job that applies the SCP will pause until you manually reboot the server.
+ type: str
+ choices: ['Graceful', 'Forced', 'NoReboot']
+ default: 'Graceful'
+ end_host_power_state:
+ description:
+ - This option is applicable for C(import) command.
+ - If C(On), End host power state is on.
+ - If C(Off), End host power state is off.
+ type: str
+ choices: ['On', 'Off']
+ default: 'On'
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/main.yml
new file mode 100644
index 000000000..c4ba1bd9c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/meta/main.yml
@@ -0,0 +1,53 @@
+galaxy_info:
+ author: Abhishek Sinha ('Abhishek-Dell')
+ description: The role performs import operation of Server Configuration Profile.
+ company: Dell Technologies
+
+ # 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.13'
+
+ # If this a Container Enabled role, provide the minimum Ansible Container version.
+ # min_ansible_container_version:
+
+ #
+ # Provide a list of supported platforms, and for each platform a list of versions.
+ # If you don't wish to enumerate all versions for a particular platform, use 'all'.
+ # To view available platforms and versions (or releases), visit:
+ # https://galaxy.ansible.com/api/v1/platforms/
+ #
+ 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.
+
+dependencies: []
+ # List your role dependencies here, one per line. Be sure to remove the '[]' above,
+ # if you add dependencies to this list.
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/converge.yml
new file mode 100644
index 000000000..29ff66275
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP from CIFS with ALL components"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'CIFS_URL') }}"
+ share_user: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'cifs_filename') }}"
+
+ - name: Verifying Import SCP from CIFS with ALL components
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from CIFS with ALL components in check mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from CIFS with ALL components in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/cifs_share/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/converge.yml
new file mode 100644
index 000000000..c0ae89edf
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/converge.yml
@@ -0,0 +1,313 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP without share_name"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target: ['IDRAC']
+ share_parameters:
+ share_user: "{{ lookup('env', 'USERNAME') }}"
+ share_password: "{{ lookup('env', 'PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'http_filename') }}"
+ ignore_errors: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP without share_name"
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "argument of type 'NoneType' is not iterable"
+
+ - name: "Importing SCP without scp_file"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target: ['IDRAC']
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ share_user: "{{ lookup('env', 'USERNAME') }}"
+ share_password: "{{ lookup('env', 'PASSWORD') }}"
+ ignore_errors: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP without scp_file"
+ ansible.builtin.assert:
+ that:
+ - "'Invalid file path provided.' in '{{ idrac_import_server_config_profile_out.msg }}' or
+ 'HTTP Error 400: Bad Request' in '{{ idrac_import_server_config_profile_out.msg }}'"
+
+ - name: "Importing SCP from CIFS with ALL components with invalid file"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'CIFS_URL') }}"
+ share_user: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+ scp_file: "invalid_file.xml"
+ ignore_errors: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP from CIFS with ALL components with invalid file"
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Invalid file path provided." or
+ idrac_import_server_config_profile_out.msg == "Failed to import scp."
+
+ - name: Wait for 15 seconds
+ ansible.builtin.pause:
+ seconds: 15
+
+ - name: "Importing SCP from CIFS with ALL components with invalid share"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "192.168.0.1:/cifsshare"
+ share_user: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'cifs_filename') }}"
+ ignore_errors: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP from CIFS with ALL components with invalid share"
+ ansible.builtin.assert:
+ that:
+ - "'HTTP Error 500' in '{{ idrac_import_server_config_profile_out.msg }}' or
+ 'Failed to import scp.' in '{{ idrac_import_server_config_profile_out.msg }}'"
+
+ - name: "Importing SCP with invalid hostname"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "randomHostname"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'CIFS_URL') }}"
+ share_user: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'cifs_filename') }}"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP with invalid hostname"
+ ansible.builtin.assert:
+ that:
+ - "'<urlopen error Unable to communicate with iDRAC randomHostname.' in '{{ idrac_import_server_config_profile_out.msg }}' or
+ '<urlopen error [Errno -2] Name or service not known>' in '{{ idrac_import_server_config_profile_out.msg }}'"
+
+ - name: "Importing SCP with invalid username"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "WrongUsername123"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'CIFS_URL') }}"
+ share_user: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'cifs_filename') }}"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP with invalid username"
+ ansible.builtin.assert:
+ that:
+ - "'HTTP Error 401' in '{{ idrac_import_server_config_profile_out.msg }}'"
+
+ - name: "Importing SCP with invalid password"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "WrongPassword@123"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'CIFS_URL') }}"
+ share_user: "{{ lookup('env', 'CIFS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'CIFS_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'cifs_filename') }}"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP with invalid password"
+ ansible.builtin.assert:
+ that:
+ - "'HTTP Error 401' in '{{ idrac_import_server_config_profile_out.msg }}'"
+
+ - name: "Importing SCP with invalid target"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target: ['idrac']
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ share_user: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ share_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'http_filename') }}"
+ ignore_errors: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP with invalid target"
+ ansible.builtin.assert:
+ that:
+ - "'value of scp_components must be one or more of: ALL, IDRAC, BIOS, NIC, RAID' in '{{ idrac_import_server_config_profile_out.msg }}'"
+
+ ############### Below snippet is commented because of Issue: JIT-284466 ###############
+ # - name: "Importing SCP with invalid username of share access"
+ # ansible.builtin.import_role:
+ # name: "idrac_import_server_config_profile"
+ # vars:
+ # hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ # username: "{{ lookup('env', 'USERNAME') }}"
+ # password: "{{ lookup('env', 'PASSWORD') }}"
+ # validate_certs: false
+ # target: ['IDRAC']
+ # share_parameters:
+ # share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ # share_user: "WrongUsername123"
+ # share_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ # scp_file: "{{ lookup('env', 'http_filename') }}"
+ # ignore_errors: true
+ # register: idrac_import_server_config_profile_status
+
+ # - name: Wait for 15 seconds
+ # ansible.builtin.pause:
+ # seconds: 15
+
+ # - name: "Verifying Import SCP with invalid username of share access"
+ # ansible.builtin.assert:
+ # that:
+ # - idrac_import_server_config_profile_out.msg == "Invalid file path provided." or
+ # idrac_import_server_config_profile_out.msg == "Failed to import scp."
+ ###################################################################################################################
+
+ ############### Below snippet is commented because of Issue: JIT-284466 ###############
+ # - name: "Importing SCP with invalid password of share access"
+ # ansible.builtin.import_role:
+ # name: "idrac_import_server_config_profile"
+ # vars:
+ # hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ # username: "{{ lookup('env', 'USERNAME') }}"
+ # password: "{{ lookup('env', 'PASSWORD') }}"
+ # validate_certs: false
+ # target: ['IDRAC']
+ # share_parameters:
+ # share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ # share_user: "{{ lookup('env', 'USERNAME') }}"
+ # share_password: "WrongPassword@123"
+ # scp_file: "{{ lookup('env', 'http_filename') }}"
+ # ignore_errors: true
+ # register: idrac_import_server_config_profile_status
+
+ # - name: "Verifying Import SCP with invalid password of share access"
+ # ansible.builtin.assert:
+ # that:
+ # - idrac_import_server_config_profile_out.msg == "Invalid file path provided." or
+ # idrac_import_server_config_profile_out.msg == "Failed to import scp."
+ ###################################################################################################################
+
+ - name: "Importing SCP with share_name as None"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target: ['IDRAC']
+ share_parameters:
+ share_name: None
+ share_user: "{{ lookup('env', 'USERNAME') }}"
+ share_password: "WrongPassword@123"
+ scp_file: "{{ lookup('env', 'http_filename') }}"
+ ignore_errors: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP with share_name as None"
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Invalid file path provided."
+
+ - name: "Importing SCP with proxy_ssupport enabled but no other proxy parameters"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target: ['ALL']
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ share_user: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ share_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'http_filename') }}"
+ proxy_support: true
+ ignore_errors: true
+ register: idrac_import_server_config_profile_status
+
+ - name: "Verifying Import SCP with proxy_ssupport enabled but no other proxy parameters"
+ ansible.builtin.assert:
+ that:
+ - "'proxy_support is True but all of the following are missing' in '{{ idrac_import_server_config_profile_out.msg }}'"
+
+ ############### Below snippet is commented because of Issue: JIT-284466 ###############
+ # - name: "Importing SCP with invalid proxy parameters"
+ # ansible.builtin.import_role:
+ # name: "idrac_import_server_config_profile"
+ # vars:
+ # hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ # username: "{{ lookup('env', 'USERNAME') }}"
+ # password: "{{ lookup('env', 'PASSWORD') }}"
+ # validate_certs: false
+ # target: ['ALL']
+ # share_parameters:
+ # share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ # share_user: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ # share_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ # scp_file: "{{ lookup('env', 'http_filename') }}"
+ # proxy_support: true
+ # proxy_type: http
+ # proxy_server: "randomProxyServer"
+ # proxy_port: "{{ lookup('env', 'PROXY_PORT') }}"
+ # proxy_password: "{{ lookup('env', 'PROXY_PASSWORD') }}"
+ # ignore_errors: true
+ # register: idrac_import_server_config_profile_status
+
+ # - name: "Verifying Import SCP with invalid proxy parameter"
+ # ansible.builtin.assert:
+ # that:
+ # - idrac_import_server_config_profile_out.msg == "Invalid file path provided." or
+ # idrac_import_server_config_profile_out.msg == "Failed to import scp."
+ ###################################################################################################################
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/molecule.yml
new file mode 100644
index 000000000..ccf982411
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/default/molecule.yml
@@ -0,0 +1,9 @@
+scenario:
+ test_sequence:
+ - dependency
+ - destroy
+ - syntax
+ - create
+ - converge
+ - cleanup
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/converge.yml
new file mode 100644
index 000000000..f9761ebc1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/converge.yml
@@ -0,0 +1,39 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+
+ - name: "Importing SCP from HTTPS"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target: "RAID"
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ share_user: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ share_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'http_filename') }}"
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from HTTP with in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from HTTP with in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/converge.yml
new file mode 100644
index 000000000..a0348544a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP from HTTP with proxy parameters"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ share_user: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ share_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'http_filename') }}"
+ proxy_support: true
+ proxy_type: http
+ proxy_server: "{{ lookup('env', 'PROXY_SERVER') }}"
+ proxy_port: "{{ lookup('env', 'PROXY_PORT') }}"
+ proxy_username: "{{ lookup('env', 'PROXY_USER') }}"
+ proxy_password: "{{ lookup('env', 'PROXY_PASSWORD') }}"
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from HTTP with proxy parameters in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from HTTP with proxy parameters in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_proxy_parameters/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/converge.yml
new file mode 100644
index 000000000..b96730d75
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP from HTTPS with ignore_certificate_warning as showerror"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTP_URL') }}"
+ share_user: "{{ lookup('env', 'HTTP_USERNAME') }}"
+ share_password: "{{ lookup('env', 'HTTP_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'http_filename') }}"
+ proxy_support: true
+ proxy_server: "{{ lookup('env', 'PROXY_SERVER') }}"
+ proxy_port: "{{ lookup('env', 'PROXY_PORT') }}"
+ proxy_username: "{{ lookup('env', 'PROXY_USER') }}"
+ proxy_password: "{{ lookup('env', 'PROXY_PASSWORD') }}"
+ ignore_certificate_warning: showerror
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from HTTP with ignore_certificate_warning as showerror in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from HTTP with ignore_certificate_warning as showerror in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/http_share_with_showerror_certificate_warning/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/converge.yml
new file mode 100644
index 000000000..7981a536c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/converge.yml
@@ -0,0 +1,37 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP from HTTPS"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTPS_URL') }}"
+ share_user: "{{ lookup('env', 'HTTPS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'HTTPS_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'https_filename') }}"
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from HTTPS in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from HTTPS in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/converge.yml
new file mode 100644
index 000000000..013505814
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/converge.yml
@@ -0,0 +1,43 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP from HTTPS with proxy parameters"
+ ansible.builtin.import_role:
+ name: "idrac_import_server_config_profile"
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'HTTPS_URL') }}"
+ share_user: "{{ lookup('env', 'HTTPS_USERNAME') }}"
+ share_password: "{{ lookup('env', 'HTTPS_PASSWORD') }}"
+ scp_file: "{{ lookup('env', 'https_filename') }}"
+ proxy_support: true
+ proxy_type: http
+ proxy_server: "{{ lookup('env', 'PROXY_SERVER') }}"
+ proxy_username: "{{ lookup('env', 'PROXY_USER') }}"
+ proxy_port: "{{ lookup('env', 'PROXY_PORT') }}"
+ proxy_password: "{{ lookup('env', 'PROXY_PASSWORD') }}"
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from HTTPS with proxy parameters in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from HTTPS with proxy parameters in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/https_share_with_proxy_parameters/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/converge.yml
new file mode 100644
index 000000000..3fbeec584
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/converge.yml
@@ -0,0 +1,36 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP from import buffer with IDRAC components"
+ ansible.builtin.import_role:
+ name: idrac_import_server_config_profile
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target:
+ - IDRAC
+ import_buffer: "{\"SystemConfiguration\": {\"Components\": [{\"FQDD\": \"iDRAC.Embedded.1\",\"Attributes\":
+ [{\"Name\": \"Time.1#Timezone\",\"Value\": \"CST6CDT\"}]}]}}"
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from import buffer with IDRAC components in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from import buffer with IDRAC components in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_json/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/converge.yml
new file mode 100644
index 000000000..bd956dc0c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/converge.yml
@@ -0,0 +1,35 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: "Importing SCP from import buffer with IDRAC components"
+ ansible.builtin.import_role:
+ name: idrac_import_server_config_profile
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target: ['IDRAC']
+ import_buffer: '<SystemConfiguration><Component FQDD="iDRAC.Embedded.1"><Attribute Name="Time.1#Timezone">CST6CDT</Attribute>
+ </Component></SystemConfiguration>'
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from import buffer with IDRAC components in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from import buffer with IDRAC components in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_buffer_xml/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/converge.yml
new file mode 100644
index 000000000..860e63b52
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/converge.yml
@@ -0,0 +1,41 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+
+ - name: "Importing SCP from NFS with multiple components"
+ ansible.builtin.import_role:
+ name: idrac_import_server_config_profile
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ target:
+ - 'NIC'
+ - 'IDRAC'
+ share_parameters:
+ share_name: "{{ lookup('env', 'NFS_URL') }}"
+ scp_file: "{{ lookup('env', 'nfs_filename') }}"
+ shutdown_type: 'Forced'
+ end_host_power_state: 'On'
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from NFS with multiple components in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from NFS with multiple components in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/import_multiple_target/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/converge.yml
new file mode 100644
index 000000000..bb839b38b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/converge.yml
@@ -0,0 +1,38 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+
+ - name: "Importing SCP from NFS"
+ ansible.builtin.import_role:
+ name: idrac_import_server_config_profile
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ share_parameters:
+ share_name: "{{ lookup('env', 'NFS_URL') }}"
+ scp_file: "{{ lookup('env', 'nfs_filename') }}"
+ shutdown_type: 'Forced'
+ end_host_power_state: 'On'
+ when: not ansible_check_mode
+
+ - name: Verifying Import SCP from NFS with in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "Successfully imported and applied Server Configuration Profile."
+ when: not ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Verifying Import SCP from NFS in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_import_server_config_profile_out.msg == "Successfully imported the Server Configuration Profile."
+ - idrac_import_server_config_profile_out.scp_status.JobState == "Completed"
+ - idrac_import_server_config_profile_out.scp_status.Message == "No changes were applied since the
+ current component configuration matched the requested configuration."
+ when: not ansible_check_mode and not idrac_import_server_config_profile_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/prepare.yml
new file mode 100644
index 000000000..5fadc24b5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/nfs_share/prepare.yml
@@ -0,0 +1,7 @@
+---
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Cleanup config
+ ansible.builtin.include_tasks: ../resources/tests/prepare.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/resources/tests/prepare.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/resources/tests/prepare.yml
new file mode 100644
index 000000000..aa9fd74c5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/molecule/resources/tests/prepare.yml
@@ -0,0 +1,18 @@
+---
+- name: "Cleanup config"
+ ansible.builtin.import_role:
+ name: idrac_import_server_config_profile
+ vars:
+ hostname: "{{ lookup('env', 'HOSTNAME') }}"
+ username: "{{ lookup('env', 'USERNAME') }}"
+ password: "{{ lookup('env', 'PASSWORD') }}"
+ validate_certs: false
+ import_buffer: "{ \"SystemConfiguration\": {\"Components\": [
+ { \"FQDD\": \"iDRAC.Embedded.1\",\"Attributes\": [{ \"Name\": \"Time.1#Timezone\",
+ \"Value\": \"UTC\",
+ \"Set On Import\": \"True\",
+ \"Comment\": \"Read and Write\" }]},{ \"FQDD\":
+ \"RAID.Integrated.1-1\",\"Attributes\": [{ \"Name\": \"RAIDrebuildRate\",
+ \"Value\": \"31\",
+ \"Set On Import\": \"True\",
+ \"Comment\": \"Read and Write\" }]}]}}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tasks/main.yml
new file mode 100644
index 000000000..0205f5990
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tasks/main.yml
@@ -0,0 +1,31 @@
+---
+# tasks file for idrac_import_server_config_profile
+
+- name: Importing the SCP components
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ hostname }}"
+ idrac_port: "{{ https_port }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ validate_certs: "{{ validate_certs }}"
+ timeout: "{{ https_timeout }}"
+ share_name: "{{ share_parameters.share_name | default(omit) }}"
+ scp_file: "{{ share_parameters.scp_file | default(omit) }}"
+ share_user: "{{ share_parameters.share_user | default(omit) }}"
+ share_password: "{{ share_parameters.share_password | default(omit) }}"
+ proxy_support: "{{ share_parameters.proxy_support | default(omit) }}"
+ proxy_type: "{{ share_parameters.proxy_type | default(omit) }}"
+ proxy_server: "{{ share_parameters.proxy_server | default(omit) }}"
+ proxy_port: "{{ share_parameters.proxy_port | default(omit) }}"
+ proxy_username: "{{ share_parameters.proxy_username | default(omit) }}"
+ proxy_password: "{{ share_parameters.proxy_password | default(omit) }}"
+ ignore_certificate_warning: "{{ share_parameters.ignore_certificate_warning | default(omit) }}"
+ import_buffer: "{{ import_buffer | default(omit) | string }}"
+ target: "{{ target }}"
+ shutdown_type: "{{ shutdown_type }}"
+ end_host_power_state: "{{ end_host_power_state }}"
+ command: 'import'
+ job_wait: "{{ idrac_import_server_config_profile_job_wait }}"
+ register: idrac_import_server_config_profile_out
+ delegate_to: "{{ idrac_import_server_config_profile_delagate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/test.yml
new file mode 100644
index 000000000..7623255a8
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/tests/test.yml
@@ -0,0 +1,5 @@
+---
+- name: Importing server config profile for iDRAC
+ hosts: localhost
+ roles:
+ - idrac_import_server_config_profile
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/vars/main.yml
new file mode 100644
index 000000000..72987b246
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_import_server_config_profile/vars/main.yml
@@ -0,0 +1,4 @@
+---
+# vars file for idrac_import_server_config_profile
+idrac_import_server_config_profile_job_wait: true
+idrac_import_server_config_profile_delagate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/README.md
new file mode 100644
index 000000000..890207bb7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/README.md
@@ -0,0 +1,181 @@
+# idrac_job_queue
+
+ Role to manage the iDRAC(iDRAC8 and iDRAC9 only) lifecycle controller job queue.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>clear_job_queue</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Clears the job queue of the iDRAC.</td>
+ </tr>
+ <tr>
+ <td>job_id</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>str</td>
+ <td>- Id of the job to be deleted.<br>- If I(clear_job_queue) is C(true) then the I(job_id) will be ignored.</td>
+ </tr>
+ <tr>
+ <td>force</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Clears the job queue of the iDRAC forcefully.</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_job_queue_out</td>
+ <td>{msg: "The job queue can been cleared successfully"
+}</td>
+<td>Module output of idrac job queue</td>
+</tbody>
+</table>
+
+## Examples
+-----
+
+```
+- name: Delete a Job
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_job_queue:
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ job_id: JID_XXXXXXXXXXXX
+
+- name: Clear the job queue
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_job_queue:
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ clear_job_queue: true
+
+- name: Clear the job queue forcefully
+ ansible.builtin.include_role:
+ name: dellemc.openmanage.idrac_job_queue:
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ clear_job_queue: true
+ force: true
+```
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Kritika Bhateja (Kritika.Bhateja@Dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/defaults/main.yml
new file mode 100644
index 000000000..afa700d6e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+# defaults file for idrac_job_queue
+validate_certs: true
+https_timeout: 30
+https_port: 443
+clear_job_queue: false
+force: false
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/handlers/main.yml
new file mode 100644
index 000000000..8b95e7024
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_job_queue
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/argument_specs.yml
new file mode 100644
index 000000000..426c7c08b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/argument_specs.yml
@@ -0,0 +1,53 @@
+---
+argument_specs:
+ main:
+ version_added: "8.0.0"
+ short_description: Role to manage the iDRAC lifecycle controller job queue.
+ description:
+ - Role to role to manage the iDRAC lifecycle controller job queue.
+ - Delete a job from the job queue
+ - Clear job queue
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ username:
+ type: str
+ description: iDRAC username.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains
+ a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The HTTPS socket level timeout in seconds.
+ type: int
+ default: 30
+ clear_job_queue:
+ description: Clear all the jobs from the iDRAC job queue.
+ type: bool
+ default: false
+ job_id:
+ description:
+ - Id of the job to be deleted.
+ - If I(clear_job_queue) is C(true) then the I(job_id) will be ignored.
+ type: str
+ force:
+ description: Clear all the jobs from the iDRAC job queue forcefully.
+ type: bool
+ default: false
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/main.yml
new file mode 100644
index 000000000..2563450dd
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/meta/main.yml
@@ -0,0 +1,28 @@
+---
+galaxy_info:
+ role_name: idrac_job_queue
+ author: "Kritika Bhateja"
+ description: Role to role to manage the iDRAC lifecycle controller job queue
+ Delete a job from the job queue
+ Clear job queue
+ company: Dell Technologies
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.13"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/converge.yml
new file mode 100644
index 000000000..6bf6af48b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/converge.yml
@@ -0,0 +1,112 @@
+---
+- name: Job Queue Clear Scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Setting input facts
+ ansible.builtin.set_fact:
+ input: &input
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ no_log: true
+
+ - name: Creating a job to which configures iDRAC attributes
+ ansible.builtin.include_role:
+ name: idrac_import_server_config_profile
+ vars:
+ <<: *input
+ target: ["NIC"]
+ import_buffer:
+ "<SystemConfiguration><Component FQDD='iDRAC.Embedded.1'><Attribute Name='IPMILan.1#Enable'>
+ Disabled</Attribute></Component></SystemConfiguration>"
+
+ - name: Clear the job queue
+ ansible.builtin.include_role:
+ name: "idrac_job_queue"
+ vars:
+ <<: *input
+ clear_job_queue: true
+
+ - name: "Verifying job queue clear"
+ ansible.builtin.assert:
+ that:
+ - idrac_job_queue_out.msg == "The job queue has been cleared successfully."
+
+ - name: Waiting for the data to be available on iDRAC
+ ansible.builtin.wait_for:
+ timeout: 180
+
+ - name: Creating a job which configures iDRAC attributes
+ ansible.builtin.include_role:
+ name: idrac_import_server_config_profile
+ vars:
+ <<: *input
+ target: ["NIC"]
+ import_buffer:
+ "<SystemConfiguration><Component FQDD='iDRAC.Embedded.1'><Attribute Name='IPMILan.1#Enable'>
+ Disabled</Attribute></Component></SystemConfiguration>"
+
+ - name: Force clear the job queue
+ ansible.builtin.include_role:
+ name: "idrac_job_queue"
+ vars:
+ <<: *input
+ clear_job_queue: true
+ force: true
+
+ - name: "Verifying force job queue clear"
+ ansible.builtin.assert:
+ that:
+ - idrac_job_queue_out.msg == "The job queue has been cleared successfully."
+
+ - name: Waiting for the data to be available on iDRAC
+ ansible.builtin.wait_for:
+ timeout: 180
+
+ - name: Clear the job queue
+ block:
+ - name: Clear the job queue when there is no jobs
+ ansible.builtin.include_role:
+ name: "idrac_job_queue"
+ vars:
+ <<: *input
+ clear_job_queue: true
+
+ rescue:
+ - name: "Verifying job queue clear when there is no job"
+ ansible.builtin.assert:
+ that:
+ - idrac_job_queue_out.msg == "There are no jobs in the job queue."
+
+ - name: Creating a job which exports SCP local path with all components
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ scp_components:
+ - IDRAC
+ share_name: "/root/"
+ scp_file: "file1.xml"
+ export_format: JSON
+ export_use: Clone
+ job_wait: false
+ async: 45
+ poll: 0
+
+ - name: Clear the job queue
+ block:
+ - name: Clear the job queue when any of the job is not in state to be deleted
+ ansible.builtin.include_role:
+ name: "idrac_job_queue"
+ vars:
+ <<: *input
+ clear_job_queue: true
+ rescue:
+ - name: "Verifying job queue clear"
+ ansible.builtin.assert:
+ that:
+ - idrac_job_queue_out.msg == "One or more jobs cannot be deleted, Retry the operation or
+ delete the jobs by checking the job status."
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/clear_job_queue/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/converge.yml
new file mode 100644
index 000000000..1d14502f8
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/converge.yml
@@ -0,0 +1,90 @@
+---
+- name: Negative Scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Creating job to export SCP local path with all components
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+ scp_components:
+ - IDRAC
+ share_name: "/root/"
+ scp_file: "file1.xml"
+ export_format: JSON
+ export_use: Clone
+ job_wait: false
+
+ - name: Deleting a job
+ block:
+ - name: Delete a job from the job queue with an invalid id
+ ansible.builtin.import_role:
+ name: "idrac_job_queue"
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+ job_id: JID_12345678
+ rescue:
+ - name: "Verifying invalid job deletion from the job queue"
+ ansible.builtin.assert:
+ that:
+ - idrac_job_queue_out.msg == "The job JID_12345678 is invalid."
+
+ - name: Clear job queue
+ block:
+ - name: Clearing job queue with an invalid hostname
+ ansible.builtin.import_role:
+ name: idrac_job_queue
+ vars:
+ hostname: "invalidHostname"
+ username: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ clear_job_queue: true
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+
+ rescue:
+ - name: "Verifying job queue clear with an invalid hostname"
+ ansible.builtin.assert:
+ that:
+ - "'<urlopen error [Errno -2] Name or service not known>' in idrac_job_queue_out.msg or
+ '<urlopen error [Errno -3] Temporary failure in name resolution>' in idrac_job_queue_out.msg"
+
+ - name: Clear job queue
+ block:
+ - name: Clearing job queue with an invalid username
+ ansible.builtin.import_role:
+ name: idrac_job_queue
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "invalidUsername"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ clear_job_queue: true
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+
+ rescue:
+ - name: "Verifying job queue clear with an invalid username"
+ ansible.builtin.assert:
+ that:
+ - "'The authentication credentials included with this request are missing or invalid.' in idrac_job_queue_out.msg"
+
+ - name: Clear job queue
+ block:
+ - name: Clearing job queue with an invalid password
+ ansible.builtin.import_role:
+ name: idrac_job_queue
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ password: "invalidPassword"
+ clear_job_queue: true
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+
+ rescue:
+ - name: "Verifying job queue clear with an invalid password"
+ ansible.builtin.assert:
+ that:
+ - "'The authentication credentials included with this request are missing or invalid.' in idrac_job_queue_out.msg"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/default/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/converge.yml
new file mode 100644
index 000000000..ecf859bf7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/converge.yml
@@ -0,0 +1,91 @@
+---
+- name: Job Deletion Scenarios
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Setting input facts
+ ansible.builtin.set_fact:
+ input: &input
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+ no_log: true
+
+ - name: Creating job which configures iDRAC attributes
+ ansible.builtin.include_role:
+ name: idrac_import_server_config_profile
+ vars:
+ <<: *input
+ target: ["NIC"]
+ import_buffer:
+ "<SystemConfiguration><Component FQDD='iDRAC.Embedded.1'><Attribute Name='IPMILan.1#Enable'>
+ Disabled</Attribute></Component></SystemConfiguration>"
+
+ - name: Delete a job from the job queue
+ ansible.builtin.include_role:
+ name: "idrac_job_queue"
+ vars:
+ <<: *input
+ job_id: "{{ idrac_import_server_config_profile_out.scp_status.Id }}"
+
+ - name: "Verifying job deletion from the job queue"
+ ansible.builtin.assert:
+ that:
+ - '"deleted sucessfully" in idrac_job_queue_out.msg'
+
+ - name: Creating job to export SCP local path with all components
+ dellemc.openmanage.idrac_server_config_profile:
+ idrac_ip: "{{ lookup('env', 'IDRAC_IP') }}"
+ idrac_user: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ idrac_password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+ scp_components:
+ - IDRAC
+ share_name: "/root/"
+ scp_file: "file1.xml"
+ export_format: JSON
+ export_use: Clone
+ job_wait: false
+ async: 45
+ poll: 0
+
+ - name: Get Job ID.
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}/redfish/v1/Managers/iDRAC.Embedded.1/Jobs"
+ validate_certs: "{{ lookup('env', 'VALIDATE_CERT') }}"
+ method: "GET"
+ user: "{{ lookup('env', 'IDRAC_USERNAME') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+ return_content: true
+ register: job
+
+ - name: Set fact for Job ID
+ ansible.builtin.set_fact:
+ jobid: "{{ job.json.Members[-1]['@odata.id'] | split('/') }}"
+
+ - name: Delete a job
+ block:
+ - name: Delete a job from the job queue which cannot be deleted
+ ansible.builtin.include_role:
+ name: "idrac_job_queue"
+ vars:
+ <<: *input
+ job_id: "{{ jobid[-1] }}"
+
+ rescue:
+ - name: "Verifying job deletion from the job queue"
+ ansible.builtin.assert:
+ that:
+ - '"cannot be deleted" in idrac_job_queue_out.msg'
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/molecule.yml
new file mode 100644
index 000000000..de4ada585
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/molecule/delete_job/molecule.yml
@@ -0,0 +1,10 @@
+---
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_api.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_api.yml
new file mode 100644
index 000000000..7120e339a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_api.yml
@@ -0,0 +1,66 @@
+---
+- name: Set uri options
+ ansible.builtin.set_fact:
+ idrac_job_queue_idrac_opts: &idrac_job_queue_idrac_opts
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers: "{{ idrac_job_queue_uri_headers }}"
+ body_format: "{{ idrac_job_queue_uri_body_format }}"
+ return_content: "{{ idrac_job_queue_uri_return_content }}"
+ force_basic_auth: "{{ idrac_job_queue_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+- name: Perform clear job queue operation for iDRAC
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}
+ {{ idrac_job_queue_clear_job_queue_api }}"
+ <<: *idrac_job_queue_idrac_opts
+ method: "POST"
+ body: '{"JobID" : "JID_CLEARALL"}'
+ status_code: [200, 400]
+ register: idrac_job_queue_clear_job_queue_out
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+ changed_when: idrac_job_queue_clear_job_queue_out.status == 200
+ when: force is undefined or force is false
+
+- name: Perform clear job queue operation with force for iDRAC
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}
+ {{ idrac_job_queue_clear_job_queue_api }}"
+ <<: *idrac_job_queue_idrac_opts
+ method: "POST"
+ body: '{ "JobID" : "JID_CLEARALL_FORCE"}'
+ status_code: 200
+ register: idrac_job_queue_clear_job_queue_force_out
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+ changed_when: idrac_job_queue_clear_job_queue_force_out.status == 200
+ when: force is defined and force is true
+
+- name: Set output Message for clear job queue successfully for iDRAC
+ ansible.builtin.set_fact:
+ idrac_job_queue_out:
+ msg: "{{ idrac_job_queue_job_clear_queue_success_msg }}"
+ when:
+ - idrac_job_queue_clear_job_queue_out is defined
+ - idrac_job_queue_clear_job_queue_out.status is defined
+ - idrac_job_queue_clear_job_queue_out.status == 200
+
+- name: Set output Message for clear job queue with force successfully for iDRAC
+ ansible.builtin.set_fact:
+ idrac_job_queue_out:
+ msg: "{{ idrac_job_queue_job_clear_queue_success_msg }}"
+ when:
+ - idrac_job_queue_clear_job_queue_force_out is defined
+ - idrac_job_queue_clear_job_queue_force_out.status is defined
+ - idrac_job_queue_clear_job_queue_force_out.status == 200
+
+- name: Set output Message for clear job queue failure for iDRAC
+ ansible.builtin.fail:
+ msg: "{{ idrac_job_queue_job_clear_queue_failure_msg }}"
+ when:
+ - idrac_job_queue_clear_job_queue_out is defined
+ - idrac_job_queue_clear_job_queue_out.status is defined
+ - idrac_job_queue_clear_job_queue_out.status == 400
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_wsman.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_wsman.yml
new file mode 100644
index 000000000..6ba7d3c7d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/clear_jobs_with_wsman.yml
@@ -0,0 +1,70 @@
+---
+- name: Set uri options
+ ansible.builtin.set_fact:
+ idrac_job_queue_idrac_opts: &idrac_job_queue_idrac_opts
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ body_format: "{{ idrac_job_queue_uri_body_format }}"
+ return_content: "{{ idrac_job_queue_uri_return_content }}"
+ force_basic_auth: "{{ idrac_job_queue_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+- name: Perform clear job queue operation for iDRAC
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/wsman"
+ <<: *idrac_job_queue_idrac_opts
+ headers:
+ Content-Type: "application/xml"
+ body: "{{ lookup('template', 'idrac_delete_job_queue.j2') }}"
+ status_code: 200
+ register: idrac_job_queue_clear_job_queue_out
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+ changed_when: idrac_job_queue_clear_job_queue_out.content
+ is search(".*<n1:MessageID>SUP020</n1:MessageID>.*")
+ when: force is undefined or force is false
+
+- name: Perform clear job queue operation with force for iDRAC
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/wsman"
+ <<: *idrac_job_queue_idrac_opts
+ headers:
+ Content-Type: "application/xml"
+ body: "{{ lookup('template', 'idrac_delete_job_queue_force.j2') }}"
+ status_code: 200
+ register: idrac_job_queue_clear_job_queue_force_out
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+ changed_when: idrac_job_queue_clear_job_queue_force_out.content
+ is search(".*<n1:MessageID>SUP020</n1:MessageID>.*")
+ when: force is defined and force is true
+
+- name: Set output Message for clear job queue successfully for iDRAC
+ ansible.builtin.set_fact:
+ idrac_job_queue_out:
+ msg: "{{ idrac_job_queue_job_clear_queue_success_msg }}"
+ when:
+ - idrac_job_queue_clear_job_queue_out is defined
+ - idrac_job_queue_clear_job_queue_out.changed is true
+ - idrac_job_queue_clear_job_queue_out.status is defined
+ - idrac_job_queue_clear_job_queue_out.status == 200
+
+- name: Set output Message for clear job queue with force successfully for iDRAC
+ ansible.builtin.set_fact:
+ idrac_job_queue_out:
+ msg: "{{ idrac_job_queue_job_clear_queue_success_msg }}"
+ when:
+ - idrac_job_queue_clear_job_queue_force_out is defined
+ - idrac_job_queue_clear_job_queue_force_out.changed is true
+ - idrac_job_queue_clear_job_queue_force_out.status is defined
+ - idrac_job_queue_clear_job_queue_force_out.status == 200
+
+- name: Set output Message for clear job queue failure for iDRAC
+ ansible.builtin.fail:
+ msg: "{{ idrac_job_queue_job_clear_queue_failure_msg }}"
+ when:
+ - idrac_job_queue_clear_job_queue_out is defined
+ - idrac_job_queue_clear_job_queue_out.changed is false
+ - idrac_job_queue_clear_job_queue_out.status is defined
+ - idrac_job_queue_clear_job_queue_out.status != 200
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/delete_job_with_id.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/delete_job_with_id.yml
new file mode 100644
index 000000000..81796c83a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/delete_job_with_id.yml
@@ -0,0 +1,41 @@
+---
+- name: Set uri options
+ ansible.builtin.set_fact:
+ idrac_job_queue_idrac_opts: &idrac_job_queue_idrac_opts
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers: "{{ idrac_job_queue_uri_headers }}"
+ body_format: "{{ idrac_job_queue_uri_body_format }}"
+ return_content: "{{ idrac_job_queue_uri_return_content }}"
+ force_basic_auth: "{{ idrac_job_queue_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+- name: Perform delete job operation
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ idrac_job_queue_validate_job_api }}/{{ job_id }}"
+ <<: *idrac_job_queue_idrac_opts
+ method: "DELETE"
+ status_code: [200, 400]
+ register: idrac_job_queue_idrac_job_delete_out
+ changed_when: idrac_job_queue_idrac_job_delete_out.status == 200
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+
+- name: Set output Message for job deleted successfully
+ ansible.builtin.set_fact:
+ idrac_job_queue_out:
+ msg: "{{ idrac_job_queue_delete_job_success_msg }}"
+ when:
+ - idrac_job_queue_idrac_job_delete_out is defined
+ - idrac_job_queue_idrac_job_delete_out.status is defined
+ - idrac_job_queue_idrac_job_delete_out.status == 200
+
+- name: Set output Message for job delete unsuccessful
+ ansible.builtin.fail:
+ msg: "{{ idrac_job_queue_delete_job_failure_msg }}"
+ when:
+ - idrac_job_queue_idrac_job_delete_out is defined
+ - idrac_job_queue_idrac_job_delete_out.status is defined
+ - idrac_job_queue_idrac_job_delete_out.status != 200
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/get_idrac_firmware_version.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/get_idrac_firmware_version.yml
new file mode 100644
index 000000000..9a5690188
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/get_idrac_firmware_version.yml
@@ -0,0 +1,20 @@
+---
+- name: Get the manager firmware version
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/Managers/iDRAC.Embedded.1"
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers: "{{ idrac_job_queue_uri_headers }}"
+ body_format: "{{ idrac_job_queue_uri_body_format }}"
+ return_content: "{{ idrac_job_queue_uri_return_content }}"
+ force_basic_auth: "{{ idrac_job_queue_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ method: GET
+ register: idrac_job_queue_firmware_version
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+
+- name: Set manager firmware version
+ ansible.builtin.set_fact:
+ idrac_job_queue_idrac_firmware_version: "{{ idrac_job_queue_firmware_version.json.FirmwareVersion }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/main.yml
new file mode 100644
index 000000000..ec2f93591
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/main.yml
@@ -0,0 +1,53 @@
+---
+# tasks file for idrac_job_queue
+- name: Check whether atleast one of 'IDRAC_USERNAME' or username is provided
+ ansible.builtin.fail:
+ msg: "Ensure the value for environment variable 'IDRAC_USERNAME' or
+ the argument 'username' is set."
+ when: username is not defined and not lookup('env', 'IDRAC_USERNAME')
+
+- name: Check whether atleast one of 'IDRAC_PASSWORD' or password is provided
+ ansible.builtin.fail:
+ msg: "Ensure the value for environment variable 'IDRAC_PASSWORD' or
+ the argument 'password' is set."
+ when: password is not defined and not lookup('env', 'IDRAC_PASSWORD')
+
+- name: Running idrac job queue role
+ when: (job_id is defined and job_id != "") or
+ (clear_job_queue is true)
+ block:
+ - name: Validate the inputs
+ ansible.builtin.include_tasks: validate_input_data.yml
+
+ - name: Delete job operation
+ ansible.builtin.include_tasks: delete_job_with_id.yml
+ when:
+ - job_id is defined and job_id != ""
+ - clear_job_queue is false
+
+ - name: Clear Job queue operation
+ when: clear_job_queue is true
+ block:
+ - name: Check firmware version
+ ansible.builtin.include_tasks: get_idrac_firmware_version.yml
+
+ - name: Clear job queue operation using rest
+ ansible.builtin.include_tasks: clear_jobs_with_api.yml
+ when: idrac_job_queue_idrac_firmware_version is version('3.0', '>=')
+
+ - name: Clear job queue operation for wsman
+ ansible.builtin.include_tasks: clear_jobs_with_wsman.yml
+ when: idrac_job_queue_idrac_firmware_version is version('3.0', '<')
+ rescue:
+ - name: Set the failure messages
+ ansible.builtin.set_fact:
+ idrac_job_queue_out: "{{ ansible_failed_result
+ | combine({'failed_task_name': ansible_failed_task.name}) }}"
+
+ always:
+ - name: Print the message
+ when: idrac_job_queue_out is defined
+ failed_when: idrac_job_queue_out.failed is defined
+ and idrac_job_queue_out.failed is true
+ ansible.builtin.debug:
+ var: idrac_job_queue_out
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/validate_input_data.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/validate_input_data.yml
new file mode 100644
index 000000000..cf88bf47c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tasks/validate_input_data.yml
@@ -0,0 +1,73 @@
+---
+- name: Set uri options
+ ansible.builtin.set_fact:
+ idrac_job_queue_idrac_opts: &idrac_job_queue_idrac_opts
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers: "{{ idrac_job_queue_uri_headers }}"
+ body_format: "{{ idrac_job_queue_uri_body_format }}"
+ return_content: "{{ idrac_job_queue_uri_return_content }}"
+ force_basic_auth: "{{ idrac_job_queue_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+- name: Get connection
+ ansible.builtin.uri:
+ <<: *idrac_job_queue_idrac_opts
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems"
+ method: "GET"
+ status_code: "{{ idrac_job_queue_uri_status_code }}"
+ register: idrac_job_queue_idrac_connection
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+
+- name: Validate hostname or certificate.
+ ansible.builtin.fail:
+ msg: "{{ idrac_job_queue_idrac_connection.msg }}"
+ when: idrac_job_queue_idrac_connection.status == -1
+
+- name: Validate credentials.
+ ansible.builtin.fail:
+ msg: "The authentication credentials included with
+ this request are missing or invalid."
+ when: idrac_job_queue_idrac_connection.status == 401
+
+- name: Check for a valid job id
+ when:
+ - job_id is defined and job_id != ""
+ - clear_job_queue is false
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+ block:
+ - name: Get the Job with the job id
+ register: idrac_job_queue_idrac_job_exists_out
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ idrac_job_queue_validate_job_api }}/{{ job_id }}"
+ <<: *idrac_job_queue_idrac_opts
+ method: "GET"
+ status_code: [200, 404]
+
+ - name: Set output Message for invalid job ID
+ ansible.builtin.fail:
+ msg: "{{ idrac_job_queue_invalid_job_msg }}"
+ when:
+ - idrac_job_queue_idrac_job_exists_out is defined
+ - idrac_job_queue_idrac_job_exists_out.status is defined
+ - idrac_job_queue_idrac_job_exists_out.status == 404
+
+- name: Check whether jobs exists to clear
+ when: clear_job_queue is true
+ delegate_to: "{{ idrac_job_queue_delegate }}"
+ block:
+ - name: Get all the jobs
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ idrac_job_queue_validate_job_api }}"
+ <<: *idrac_job_queue_idrac_opts
+ method: "GET"
+ status_code: [200, 404]
+ register: idrac_job_queue_jobs_exists_out
+
+ - name: Set output Message if jobs doesnt exist
+ ansible.builtin.fail:
+ msg: "{{ idrac_job_queue_no_jobs_in_queue_msg }}"
+ when: idrac_job_queue_jobs_exists_out.json['Members@odata.count'] == 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue.j2 b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue.j2
new file mode 100644
index 000000000..0b03144cc
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue.j2
@@ -0,0 +1,25 @@
+<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:n1="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_JobService">
+ <s:Header>
+ <wsa:To s:mustUnderstand="true">https://{{ hostname }}:{{ https_port }}/wsman</wsa:To>
+ <wsman:ResourceURI s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_JobService</wsman:ResourceURI>
+ <wsa:ReplyTo>
+ <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
+ </wsa:ReplyTo>
+ <wsa:Action s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_JobService/DeleteJobQueue</wsa:Action>
+ <wsman:MaxEnvelopeSize s:mustUnderstand="true">524288</wsman:MaxEnvelopeSize>
+ <wsa:MessageID s:mustUnderstand="true">urn:uuid:{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=32') | to_uuid }}</wsa:MessageID>
+ <wsman:OperationTimeout>PT12.0S</wsman:OperationTimeout>
+ <wsman:SelectorSet>
+ <wsman:Selector Name="__cimnamespace">root/dcim</wsman:Selector>
+ <wsman:Selector Name="SystemName">Idrac</wsman:Selector>
+ <wsman:Selector Name="SystemCreationClassName">DCIM_ComputerSystem</wsman:Selector>
+ <wsman:Selector Name="Name">JobService</wsman:Selector>
+ <wsman:Selector Name="CreationClassName">DCIM_JobService</wsman:Selector>
+ </wsman:SelectorSet>
+ </s:Header>
+ <s:Body>
+ <n1:DeleteJobQueue_INPUT>
+ <n1:JobID>JID_CLEARALL</n1:JobID>
+ </n1:DeleteJobQueue_INPUT>
+ </s:Body>
+</s:Envelope>
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue_force.j2 b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue_force.j2
new file mode 100644
index 000000000..efa38f0d2
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/templates/idrac_delete_job_queue_force.j2
@@ -0,0 +1,25 @@
+<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:n1="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_JobService">
+ <s:Header>
+ <wsa:To s:mustUnderstand="true">https://{{ hostname }}:{{ https_port }}/wsman</wsa:To>
+ <wsman:ResourceURI s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_JobService</wsman:ResourceURI>
+ <wsa:ReplyTo>
+ <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
+ </wsa:ReplyTo>
+ <wsa:Action s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_JobService/DeleteJobQueue</wsa:Action>
+ <wsman:MaxEnvelopeSize s:mustUnderstand="true">524288</wsman:MaxEnvelopeSize>
+ <wsa:MessageID s:mustUnderstand="true">urn:uuid:{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=32') | to_uuid }}</wsa:MessageID>
+ <wsman:OperationTimeout>PT12.0S</wsman:OperationTimeout>
+ <wsman:SelectorSet>
+ <wsman:Selector Name="__cimnamespace">root/dcim</wsman:Selector>
+ <wsman:Selector Name="SystemName">Idrac</wsman:Selector>
+ <wsman:Selector Name="SystemCreationClassName">DCIM_ComputerSystem</wsman:Selector>
+ <wsman:Selector Name="Name">JobService</wsman:Selector>
+ <wsman:Selector Name="CreationClassName">DCIM_JobService</wsman:Selector>
+ </wsman:SelectorSet>
+ </s:Header>
+ <s:Body>
+ <n1:DeleteJobQueue_INPUT>
+ <n1:JobID>JID_CLEARALL_FORCE</n1:JobID>
+ </n1:DeleteJobQueue_INPUT>
+ </s:Body>
+</s:Envelope>
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/test.yml
new file mode 100644
index 000000000..c430ba1ce
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Testing for idrac job queue
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_job_queue
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/vars/main.yml
new file mode 100644
index 000000000..4d8a2a593
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_job_queue/vars/main.yml
@@ -0,0 +1,30 @@
+---
+# vars file for idrac_job_queue
+idrac_job_queue_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+idrac_job_queue_uri_body_format: "json"
+idrac_job_queue_force_basic_auth: true
+idrac_job_queue_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+idrac_job_queue_uri_return_content: true
+idrac_job_queue_validate_job_api: /redfish/v1/Managers/iDRAC.Embedded.1/Jobs
+idrac_job_queue_clear_job_queue_api:
+ /redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellJobService/Actions/DellJobService.DeleteJobQueue
+idrac_job_queue_delete_job_success_msg: The job {{ job_id }} has been deleted
+ sucessfully.
+idrac_job_queue_delete_job_failure_msg: "The job {{ job_id }} cannot be
+ deleted, Retry the operation by checking the job status."
+idrac_job_queue_invalid_job_msg: "The job {{ job_id }} is invalid."
+idrac_job_queue_job_clear_queue_success_msg: "The job queue
+ has been cleared successfully."
+idrac_job_queue_no_jobs_in_queue_msg: "There are no jobs in the job queue."
+idrac_job_queue_job_clear_queue_failure_msg: "One or more jobs cannot be
+ deleted, Retry the operation or delete the jobs by checking the job status."
+idrac_job_queue_delegate: "{{ lookup('ansible.builtin.env', 'RUNON',
+ default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/README.md
new file mode 100644
index 000000000..a86526f03
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/README.md
@@ -0,0 +1,509 @@
+idrac_os_deployment
+=========
+
+Role to deploy operating system and version on the servers.</br>
+
+The role perform the following operations:
+1. Downloads or copies the source ISO as a local copy in the ansible controller machine tmp folder.
+1. Create a kickstart file using jinja template based on the os name and version .
+1. Extract the ISO using the `xorriso` library.
+1. Enable the extracted ISO to use kickstart file by modifying the boot configurations for bios and uefi.
+1. Compile the iso to generate a custom iso by embedding the kickstart file in an iso using the `mkisofs`, `isohybrid` and `implantisomd5` commands.
+1. Copy the custom ISO generated to destination share location as specfied to the role input. Based on the input a following method is used to copy the destination to a shared repository.
+ - CIFS/NFS uses the local file mount to copy the ISO to a location.
+ - HTTP/HTTPS uses the SSH to copy/transfer the ISO to a location where the web server content is served.
+1. Using an iDRAC `idrac_virtual_media` module mount the custom ISO as virtual media (virtual CD) in an iDRAC.
+1. Using an iDRAC `idrac_boot` module set the boot target to CD and enable a reboot to CD once.
+1. Track for the OS deployment for the specified amount of user input time.
+1. Eject the virtual media after the specfied time is finished.
+
+Requirements
+------------
+
+### Prerequisite
+* To Support the HTTP/HTTPS repository as a destination an ssh to a target machine should be enabled to copy the custom iso into a http/https share location.
+* To Support the CIFS/NFS repository as a destination the repository needs to be manually mounted to local (ansible controller) copy the custom iso into locally mounted CIFS/NFS share location.
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+python
+xorriso
+syslinux
+isomd5sum
+wget
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+xorriso
+syslinux
+isomd5sum
+wget
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+ansible.utils
+ansible.windows
+```
+Role Variables
+--------------
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC IP Address or hostname</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC username with admin privilages</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td> The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>os_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The operating system name to match the jinja template of the kickstart file.</br>- Supported os name is versions for RHEL and ESXI.</br>- Jinja template file should exists in the format `os_name_upper_os_version_major.j2`</td>
+ </tr>
+ <tr>
+ <td>os_version</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The operating system version to match the jinja template of the kickstart file.</br>- Supported versions for RHEL are 9.x and 8.x and for ESXi is 8.x.</br> - Jinja template file should exists in the format `os_name_upper_os_version_major.j2`</td>
+ </tr>
+ <tr>
+ <td>source</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>HTTP/HTTPS share or local path of the ISO.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protocol</td>
+ <td>true</td>
+ <td></td>
+ <td>["https", "http", "local", "cifs", "nfs"]</td>
+ <td>str</td>
+ <td>- Type of the the transfer protocol used to download the iso.<br/>- C(https) uses the https protocol to download the iso.<br/>- C(http) uses the http protocol to download the iso.<br/>- C(nfs) uses the locally mounted nfs folder path to download the iso.<br/>- C(cifs) uses the locally mounted cifs folder path to download the iso.<br/>- C(local) uses the local folder path to download the iso.<br/>- If I(custom_iso_true) is C(true) this will be used to mount the custom iso to virtual media.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- HTTP/HTTPS address to download the ISO.<br/>- Hostname of the http/https/cifs and nfs to mount the custom iso to virtual media.<br/>- I(hostname) is applicable to download iso only when I(protocol) is C(http) or C(https) and I(is_custom_iso) is C(false).<br/>- I(hostname) is ignored to download the iso when I(protocol) is C(local), C(nfs) or C(cifs) and I(is_custom_iso) is C(false).<br/>- I(hostname) will be used to attach the virtual media when I(is_custom_iso) is C(true).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iso_path</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- Absolute local path or http/https share path of the iso.<br/>- when I(custom_iso) true I(iso_path) should be http, https, nfs or cifs path.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iso_name</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>Name of the iso file.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ks_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- Absolute local path or http/https share path kickstart file.<br/>- When I(ks_path) is provided role skips the generation of kickstart file and uses the one provided in the input.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is_custom_iso</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Specifies the source iso is a custom iso.<br/>- C(true) uses the custom iso and skips the kickstart file generation and custom iso compilation.<br/>- when C(true), I(destination) is ignored and uses the I(iso_path) to mount the virtual media on idrac.<br/>- C(false) runs the the kickstart file generation and custom iso compilation</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;username</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Username of the http, https and cifs share.<br/>- I(username) is applicable only when I(protocol) is C(http) , C(https) to download the iso file.<br/>- I(username) is used to mount the virtual media on idrac and applicable when I(protocol) is C(http), C(https) or C(cifs) and I(is_custom_iso) is C(true).<br/>- I(username) is ignored when I(protocol) is C(local).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;password</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Password of the http, https and cifs share.<br/>- I(password) is applicable only when I(protocol) is C(http) , C(https) to download the iso file.<br/>- I(password) is applicable to mount the custom iso as a virtual media in idrac when I(protocol) is C(http) , C(https), c(cifs) and I(is_custom_iso) is C(true).<br/>- I(password) is ignored when I(protocol) is C(local).</td>
+ </tr>
+ <tr>
+ <td>destination</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- Share path to mount the ISO to iDRAC.<br/>- Share needs to have a write permission to copy the generated ISO.<br/>- CIFS, NFS, HTTP and HTTPS shares are supported.<br/>- I(destination) is ignored when I(is_custom_iso) is C(true)<br>- When the protocol is of C(http), C(https) custom iso is copied into a destination location/folder where the web server content is served.<br/>- When the protocol is of C(cifs), c(nfs) custom iso is copied into the locally mounted nfs or cifs location location.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protocol</td>
+ <td>true</td>
+ <td></td>
+ <td>["https", "http", "nfs", "cifs"]</td>
+ <td>str</td>
+ <td>- Type of the the transfer protocol used to mount the virtual media on to idrac.- C(https) uses the ssh protocol to copy the custom iso to the I(mountpoint) and uses https protocol to the mount the virtual media.- C(http) uses the ssh protocol to copy the custom iso to the I(mountpoint) and uses https protocol to the mount the virtual media.- C(nfs) copies the the custom iso to the I(mountpoint) mounted localy and uses nfs protocol to the mount the virtual media.- C(cifs) copies the the custom iso to the I(mountpoint) mounted localy and uses cifs protocol to the mount the virtual media.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Target machine address/hostname where the custom iso will be copied.<br/>- Address/hostname used to mount the iso as a virtual media.<br/>- I(hostname) is applicable to copy iso using ssh when I(protocol) is C(http) or C(https).<br/>- I(hostname) will be defaulted to localhost to copy iso when I(protocol) is C(nfs), C(cifs).<br/> - I(hostname) will be used to mount the virtual media in idrac when I(protocol) is C(http), C(https), C(nfs) or C(cifs).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iso_path</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>Custom iso absolute path to be used to mount as a virtual media in idrac.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iso_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>Custom iso file name. If not specified defaulted to C(hostname-source.iso_name).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mountpoint</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- Target machine absolute path where the custom iso will be copied.<br/>- I(mountpoint) will be path where http/https is served from when I(protocol) is C(http), C(https).<br/>- I(mountpoint) will be local folder mounted with nfs/cifs share when I(protocol) is C(nfs) C(cifs).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os_type</td>
+ <td>false</td>
+ <td>linux</td>
+ <td>["linux", "windows"]</td>
+ <td>str</td>
+ <td>HTTP/HTTPS share based on linux/Windows.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;username</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>Username of the http/https/cifs share where customized ISO is used to mount as a virtual media.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;password</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>Password of the http/https/cifs share where customized ISO is used to mount as a virtual media.</td>
+ </tr>
+ <tr>
+ <td>wait_for_os_deployment</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>Wait for the OS deployment to finish.</td>
+ </tr>
+ <tr>
+ <td>os_deployment_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>Time in minutes to wait for the OS deployment to finish.</td>
+ </tr>
+ <tr>
+ <td>eject_iso</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Eject the virtual media (ISO) after the tracking of OS deployment is finished.<br/>- ISO will be ejected if I(eject_iso) is C(true) and I(wait_for_os_deployment) is C(true).</td>
+ </tr>
+ <tr>
+ <td>delete_custom_iso</td>
+ <td>false</td>
+ <td></td>
+ <td>true</td>
+ <td>bool</td>
+ <td>- Deletes the Custom iso after the OS deployment is finshed.<br/>- ISO will be delete if I(delete_custom_iso) is C(true) and I(wait_for_os_deployment) is C(true).</td>
+ </tr>
+</tbody>
+</table>
+
+## SSH ansible Variables
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>ansible_ssh_user</td>
+ <td>user</td>
+ <td>Username of the target ssh machine where the custom iso is copied</br>This is used copy/ssh the custom ISO to the destination folder where http/https web server serves the content.</td>
+ </tr>
+ <tr>
+ <td>ansible_ssh_password</td>
+ <td>password</td>
+ <td>Password of the target ssh machine where the custom iso is copied</br>This is used copy/ssh the custom ISO to the destination folder where http/https web server serves the content.</td>
+ </tr>
+ <tr>
+ <td>ansible_remote_tmp</td>
+ <td>C://User//tmp</td>
+ <td>Temp directory of the target ssh machine where the custom iso is copied</br>This is used copy/ssh the custom ISO to the destination folder where http/https web server serves the content.</td>
+ </tr>
+ <tr>
+ <td>become_method</td>
+ <td>runas</td>
+ <td>Overrides the default method of shh</br>This is used copy/ssh the custom ISO to the destination folder where http/https web server serves the content.</td>
+ </tr>
+ <tr>
+ <td>shell_type</td>
+ <td>cmd</td>
+ <td>Defines the shell type to be used on the target ssh machine where the custom iso is copied</br>This is used copy/ssh the custom ISO to the destination folder where http/https web server serves the content.</td>
+ </tr>
+ </tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_os_deployment_out</td>
+ <td>Successfully deployed the Operating System</td>
+ <td>Output of the OS deployment role.</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_failure</td>
+ <td>The combination of OS name %s and version %s is not supported.</td>
+ <td>Error result of the task</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_kickstart_file</td>
+ <td>/tmp/omam_osd_kufwni/kickstart.cfg</td>
+ <td>Path of the kickstart file generated or downloaded</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_iso_file</td>
+ <td>/tmp/omam_osd_kufwni/rhel.iso</td>
+ <td>Path of the iso file downloaded</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_iso_extract_dir</td>
+ <td>/tmp/omam_osd_kufwni/extract</td>
+ <td>Path of the extract folder created within the tmp directory</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_custom_iso_filename</td>
+ <td>198.192.0.1_rhel.iso</td>
+ <td>Filename of the custom iso file genereated</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_custom_iso_file</td>
+ <td>/tmp/omam_osd_kufwni/198.192.0.1_rhel.iso</td>
+ <td>Path of the custom iso file genereated</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_hybrid_cmd</td>
+ <td>isohybrid --uefi /tmp/omam_osd_kufwni/198.192.0.1_rhel.iso</td>
+ <td>Command isohybrid applied the custom iso file</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_checksum_cmd</td>
+ <td>implantisomd5 --uefi /tmp/omam_osd_kufwni/198.192.0.1_rhel.iso</td>
+ <td>Command to implant md5 checksum on the custom iso file</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_xorriso_cmd</td>
+ <td>xorriso -osirrox -indev /tmp/omam_osd_kufwni/rhel.iso -extract / /tmp/omam_osd_kufwni/extract</td>
+ <td>Command xorisso to extract the downloaded iso</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_delegate</td>
+ <td>localhost</td>
+ <td>Enables the delgate task to run on localhost or container in case of molecules</td>
+ </tr>
+ <tr>
+ <td>idrac_os_deployment_supported_os</td>
+ <td>{ RHEL: ["8", "9"], ESXI: ["8"] }</td>
+ <td>Hold the map data of supported os name and version</td>
+ </tr>
+ </tbody>
+</table>
+
+## Env Varaibles
+
+When we have to SSH into a machine a fingerprint has to be added into the ansible controller machine for it to connect succesfully, if you trust the machine you are copying you use the below environment variable disable the fingerprint check.
+
+```export ANSIBLE_HOST_KEY_CHECKING=False```
+
+Example Playbook
+----------------
+
+```
+- name: Generate Kickstart file, custom iso and install RHEL OS
+ ansible.builtin.import_role:
+ name: idrac_os_deployment
+ vars:
+ hostname: 192.168.0.1
+ username: root
+ password: password
+ os_name: RHEL
+ os_version: 9
+ source:
+ protocol: https
+ hostname: 198.192.0.1
+ iso_path: /to/iso
+ iso_name: rhel9.iso
+ destination:
+ protocol: https
+ hostname: 198.192.0.1
+ mountpath: /user/www/myrepo
+ os_type: linux
+ iso_path: /to/iso
+```
+```
+- name: Generate custom iso using a kickstart file and install RHEL OS
+ ansible.builtin.import_role:
+ name: idrac_os_deployment
+ vars:
+ hostname: 192.168.0.1
+ username: root
+ password: password
+ ca_path: path/to/ca
+ os_name: RHEL
+ os_version: 9
+ source:
+ protocol: https
+ hostname: 198.192.0.1
+ ks_path: /to/iso/rhel-9.cfg
+ path: /to/iso
+ iso_name: rhel9.iso
+ destination:
+ protocol: https
+ hostname: 198.192.0.1
+ mountpath: /user/www/myrepo
+ os_type: linux
+ iso_path: /to/iso
+```
+```
+- name: Install RHEL OS using a custom iso
+ ansible.builtin.import_role:
+ name: idrac_os_deployment
+ vars:
+ hostname: 192.168.0.1
+ username: root
+ password: password
+ os_name: RHEL
+ os_version: 9
+ source:
+ protocol: https
+ hostname: 198.192.0.1
+ iso_path: /to/iso
+ iso_name: custom-rhel.iso
+ is_custom_iso: true
+```
+Author Information
+------------------
+Dell Technologies <br>
+Sachin Apagundi (Sachin_Apagundi@Dell.com) 2023 <br>
+Abhishek Sinha (Abhishek.Sinha10@Dell.com) 2023 <br>
+Jagadeesh N V (Jagadeesh.N.V@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/esxi.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/esxi.yml
new file mode 100644
index 000000000..9f3c4f570
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/esxi.yml
@@ -0,0 +1,20 @@
+esxi_keyboard: null
+esxi_rootpw: ""
+esxi_iscrypted: false
+esxi_reboot: true
+esxi_install_type: install
+esxi_install_options: ["--firstdisk", "--overwritevmfs"]
+esxi_clearpart: ["--alldrives", "--overwritevmfs"]
+esxi_network: false
+esxi_partition: false
+esxi_serial_num: null
+esxi_firstboot:
+ interpreter: busybox
+ args:
+ - vim-cmd hostsvc/enable_ssh
+ - vim-cmd hostsvc/start_ssh
+ - vim-cmd hostsvc/enable_esx_shell
+ - vim-cmd hostsvc/start_esx_shell
+ - esxcli system settings advanced set -o /UserVars/SuppressShellWarning -i 1
+esxi_prescript: null
+esxi_postscript: null
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/main.yml
new file mode 100644
index 000000000..0b3c26f4f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/main.yml
@@ -0,0 +1,9 @@
+---
+https_port: 443
+https_timeout: 30
+validate_certs: true
+os_deployment_timeout: 30
+eject_iso: true
+wait_for_os_deployment: true
+delete_custom_iso: true
+set_no_log: true
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/rhel.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/rhel.yml
new file mode 100644
index 000000000..8fadadde4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/defaults/main/rhel.yml
@@ -0,0 +1,16 @@
+rhel_keyboard: us
+rhel_lang: en_US
+rhel_timezone: ["America/New_York", "--utc"]
+rhel_rootpw: ""
+rhel_iscrypted: false
+rhel_reboot: true
+rhel_install_source: cdrom # nfs --server=nfs://10.1.2.3 --dir=/ins/tree
+rhel_bootloader: [] # RHEL 8 and 9 have different defaults
+rhel_zerombr: true
+rhel_clearpart: ["--all", "--initlabel"]
+rhel_autopart: []
+rhel_firstboot: ["--disable"]
+rhel_firewall: ["--enabled"]
+rhel_selinux: ["--enforcing"]
+rhel_packages: ["@^minimal-environment"]
+rhel_network: false
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/handlers/main.yml
new file mode 100644
index 000000000..05452dfd5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_os_deployment
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/argument_specs.yml
new file mode 100644
index 000000000..e1b4935aa
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/argument_specs.yml
@@ -0,0 +1,191 @@
+---
+argument_specs:
+ main:
+ version_added: "7.5.0"
+ short_description: Role to deploy operating system on the iDRAC servers
+ description:
+ - Role to generate the custom iso using the kickstart configuration file and deploy operating system on the idrac servers.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address or hostname.
+ username:
+ type: str
+ description: iDRAC username with admin privilages.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description: The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ os_name:
+ type: str
+ description:
+ - The operating system name to match the jinja template of the kickstart file.
+ - Supported os name is versions for RHEL and ESXI.
+ - Jinja template file should exists in the format <os_name_upper>_<os_version_major>.j2
+ - This is required when I(is_custom_iso) is C(false).
+ os_version:
+ type: str
+ description:
+ - The operating system version to match the jinja template of the kickstart file.
+ - Supported versions for RHEL are 9.x and 8.x and for ESXi is 8.x.
+ - Jinja template file should exists in the format <os_name_upper>_<os_version_major>.j2
+ - This is required when I(is_custom_iso) is C(false)
+ source:
+ type: dict
+ description: HTTP/HTTPS share or local path of the ISO.
+ required: true
+ options:
+ protocol:
+ type: str
+ description:
+ - Type of the the transfer protocol used to download the iso.
+ - C(https) uses the https protocol to download the iso.
+ - C(http) uses the http protocol to download the iso.
+ - C(nfs) uses the locally mounted nfs folder path to download the iso.
+ - C(cifs) uses the locally mounted cifs folder path to download the iso.
+ - C(local) uses the local folder path to download the iso.
+ - If I(custom_iso_true) is C(true) this will be used to mount the custom iso to virtual media.
+ choices: ["https", "http", "local", "cifs", "nfs"]
+ required: true
+ hostname:
+ type: str
+ description:
+ - HTTP/HTTPS address to download the ISO.
+ - Hostname of the http/https/cifs and nfs to mount the custom iso to virtual media.
+ - I(hostname) is applicable to download iso only when I(protocol) is C(http) or C(https) and I(is_custom_iso) is C(false).
+ - I(hostname) is ignored to download the iso when I(protocol) is C(local), C(nfs) or C(cifs) and I(is_custom_iso) is C(false).
+ - I(hostname) will be used to attach the virtual media when I(is_custom_iso) is C(true).
+ iso_path:
+ type: path
+ description:
+ - Absolute local path or http/https share path of the iso.
+ - when I(custom_iso) true I(iso_path) should be http, https, nfs or cifs path.
+ required: true
+ iso_name:
+ type: str
+ description: Name of the iso file.
+ required: true
+ ks_path:
+ type: path
+ description:
+ - Absolute local path or http/https share path kickstart file.
+ - When I(ks_path) is provided role skips the generation of kickstart file and uses the one provided in the input.
+ is_custom_iso:
+ type: bool
+ description:
+ - Specifies the source iso is a custom iso.
+ - C(true) uses the custom iso and skips the kickstart file generation and custom iso compilation.
+ - when C(true), I(destination) is ignored and uses the I(iso_path) to mount the virtual media on idrac.
+ - C(false) runs the the kickstart file generation and custom iso compilation
+ default: false
+ username:
+ type: str
+ description:
+ - Username of the http, https and cifs share.
+ - I(username) is applicable only when I(protocol) is C(http) , C(https) to download the iso file.
+ - I(username) is applicable to mount the custom iso as a virtual media in idrac when I(protocol) is
+ C(http) , C(https), c(cifs) and I(is_custom_iso) is C(true).
+ - I(username) is ignored when I(protocol) is C(local).
+ password:
+ type: str
+ description:
+ - Password of the http, https and cifs share.
+ - I(password) is applicable only when I(protocol) is C(http) , C(https) to download the iso file.
+ - I(password) is applicable to mount the custom iso as a virtual media in idrac when
+ I(protocol) is C(http) , C(https), c(cifs) and I(is_custom_iso) is C(true).
+ - I(password) is ignored when I(protocol) is C(local).
+ destination:
+ type: dict
+ description:
+ - Share path to mount the ISO to iDRAC.
+ - Share needs to have a write permission to copy the generated ISO.
+ - CIFS, NFS, HTTP and HTTPS shares are supported.
+ - I(destination) is ignored when I(is_custom_iso) is C(true)
+ - When the protocol is of C(http), C(https) custom iso is copied into a destination location/folder where the web server content is served.
+ - When the protocol is of C(cifs), c(nfs) custom iso is copied into the locally mounted nfs or cifs location location.
+ options:
+ protocol:
+ type: str
+ description:
+ - Type of the the transfer protocol used to mount the virtual media on to idrac.
+ - C(https) uses the ssh protocol to copy the custom iso to the I(mountpoint) and uses https protocol to the mount the virtual media.
+ - C(http) uses the ssh protocol to copy the custom iso to the I(mountpoint) and uses https protocol to the mount the virtual media.
+ - C(nfs) copies the the custom iso to the I(mountpoint) mounted localy and uses nfs protocol to the mount the virtual media.
+ - C(cifs) copies the the custom iso to the I(mountpoint) mounted localy and uses cifs protocol to the mount the virtual media.
+ choices: ["https", "http", "nfs", "cifs"]
+ required: true
+ hostname:
+ type: str
+ description:
+ - Target machine address/hostname where the custom iso will be copied.
+ - Address/hostname used to mount the iso as a virtual media.
+ - I(hostname) is applicable to copy iso using ssh when I(protocol) is C(http) or C(https).
+ - I(hostname) will be defaulted to localhost to copy iso when I(protocol) is C(nfs), C(cifs).
+ - I(hostname) will be used to mount the virtual media in idrac when I(protocol) is C(http), C(https), C(nfs) or C(cifs).
+ required: true
+ iso_path:
+ type: path
+ description: Custom iso absolute path to be used to mount as a virtual media in idrac.
+ required: true
+ iso_name:
+ type: str
+ description: Custom iso file name. If not specified defaulted to C(hostname-source.iso_name).
+ mountpoint:
+ type: path
+ description:
+ - Target machine absolute path where the custom iso will be copied.
+ - I(mountpoint) will be path where http/https is served from when I(protocol) is C(http), C(https).
+ - I(mountpoint) will be local folder mounted with nfs/cifs share when I(protocol) is C(nfs) C(cifs).
+ required: true
+ os_type:
+ description: HTTP/HTTPS share based on linux/Windows.
+ type: str
+ choices: ["linux", "windows"]
+ default: "linux"
+ username:
+ type: str
+ description:
+ - Username of the http/https/cifs share where customized ISO is used to mount as a virtual media.
+ password:
+ type: str
+ description:
+ - Password of the http/https/cifs share where customized ISO is used to mount as a virtual media.
+ wait_for_os_deployment:
+ default: true
+ type: bool
+ description:
+ - Wait for the OS deployment to finish.
+ os_deployment_timeout:
+ description:
+ - Time in minutes to wait for the OS deployment to finish.
+ default: 30
+ type: int
+ eject_iso:
+ description:
+ - Eject the virtual media (ISO) after the tracking of OS deployment is finished.
+ - ISO will be ejected if I(eject_iso) is C(true) and I(wait_for_os_deployment) is C(true).
+ default: true
+ type: bool
+ delete_custom_iso:
+ description:
+ - Deletes the Custom iso after the OS deployment is finshed.
+ - ISO will be delete if I(delete_custom_iso) is C(true) and I(wait_for_os_deployment) is C(true).
+ default: true
+ type: bool
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/main.yml
new file mode 100644
index 000000000..dda8bed03
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/meta/main.yml
@@ -0,0 +1,19 @@
+galaxy_info:
+ author: |
+ "Sachin Apagundi
+ Abhishek Sinha
+ Jagadeesh N V"
+ description: Role to deploy the operating system on idrac servers.
+ company: Dell Technologies
+ license: GPL-3.0-only
+ min_ansible_version: "2.13"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_destinations.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_destinations.yml
new file mode 100644
index 000000000..a07ce47fc
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_destinations.yml
@@ -0,0 +1,25 @@
+---
+- name: Remove custom iso from mounted path
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ when: destination.protocol in ['nfs', 'cifs']
+ ansible.builtin.file:
+ state: absent
+ path: "{{ destination.mountpoint }}/{{ idrac_os_deployment_custom_iso_filename }}"
+
+- name: Remove custom iso from HTTP or HTTPS share on Linux
+ delegate_to: "{{ destination.hostname }}"
+ when:
+ - destination.protocol in ['http', 'https']
+ - destination.os_type is undefined or destination.os_type == 'linux'
+ ansible.builtin.file:
+ path: "{{ destination.mountpoint }}/{{ idrac_os_deployment_custom_iso_filename }}"
+ state: absent
+
+- name: Remove custom iso to HTTP or HTTPS share on windows
+ delegate_to: "{{ destination.hostname }}"
+ when:
+ - destination.protocol in ['http', 'https']
+ - destination.os_type is undefined or destination.os_type == 'windows'
+ ansible.windows.win_file:
+ path: "{{ destination.mountpoint }}/{{ idrac_os_deployment_custom_iso_filename }}"
+ state: absent
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_working_directory.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_working_directory.yml
new file mode 100644
index 000000000..f3edec438
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/clean_up/clean_up_working_directory.yml
@@ -0,0 +1,7 @@
+- name: Clean up the working directory
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ when: idrac_os_deployment_wd is defined
+ ansible.builtin.file:
+ path: "{{ idrac_os_deployment_wd.path }}"
+ state: absent
+ failed_when: false
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/copy_iso_to_destination.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/copy_iso_to_destination.yml
new file mode 100644
index 000000000..b5c6f52f5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/copy_iso_to_destination.yml
@@ -0,0 +1,60 @@
+---
+- name: Copy the custom iso local destination
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ when: destination.protocol in ['nfs', 'cifs']
+ block:
+ - name: Ensure file already exists at destination dest to work around 'invalid selinux context' issue
+ ansible.builtin.file:
+ path: "{{ destination.mountpoint }}/{{ idrac_os_deployment_custom_iso_filename }}"
+ state: touch
+ mode: "{{ idrac_os_deployment_dest_mode }}"
+
+ - name: Copy custom iso to mounted path
+ register: idrac_os_deployment_copy_to_destination
+ ansible.builtin.copy:
+ src: "{{ idrac_os_deployment_custom_iso_file }}"
+ dest: "{{ destination.mountpoint }}"
+ mode: "{{ idrac_os_deployment_dest_mode }}"
+
+- name: Copy custom iso to HTTP or HTTPS share on linux
+ when:
+ - destination.protocol in ['http', 'https']
+ - destination.os_type is undefined or destination.os_type == 'linux'
+ delegate_to: "{{ destination.hostname }}"
+ block:
+ - name: Copy the iso to linux destiantion
+ ignore_unreachable: true
+ register: idrac_os_deployment_copy_to_destination
+ ansible.builtin.copy:
+ src: "{{ idrac_os_deployment_custom_iso_file }}"
+ dest: "{{ destination.mountpoint }}"
+ mode: "preserve"
+
+ - name: Fail if destination is unreachable
+ when: idrac_os_deployment_copy_to_destination is unreachable
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_copy_to_destination }}"
+
+- name: Copy custom iso to HTTP or HTTPS share on windows
+ delegate_to: "{{ destination.hostname }}"
+ when:
+ - destination.protocol in ['http', 'https']
+ - destination.os_type is defined and destination.os_type == 'windows'
+ block:
+ - name: Copy the iso to windows destination
+ ignore_unreachable: true
+ register: idrac_os_deployment_copy_to_destination
+ ansible.windows.win_copy:
+ src: "{{ idrac_os_deployment_custom_iso_file }}"
+ dest: "{{ destination.mountpoint }}"
+ mode: "preserve"
+
+ - name: Fail if destination is unreachable
+ when: idrac_os_deployment_copy_to_destination is unreachable
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_copy_to_destination }}"
+
+- name: Set Copy to destination flag
+ when: idrac_os_deployment_copy_to_destination is succeeded
+ ansible.builtin.set_fact:
+ idrac_os_deployment_copied_to_destination: true
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/create_working_directory_path.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/create_working_directory_path.yml
new file mode 100644
index 000000000..10560dba7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/create_working_directory_path.yml
@@ -0,0 +1,28 @@
+---
+- name: Create working directory
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.tempfile:
+ state: directory
+ prefix: "{{ idrac_os_deployment_temp_file_prefix }}"
+ register: idrac_os_deployment_wd
+
+- name: Set custom iso filename
+ when: destination is defined and destination.iso_name is defined
+ ansible.builtin.set_fact:
+ idrac_os_deployment_custom_iso_filename: "{{ destination.iso_name }}"
+
+- name: Set custom iso path
+ ansible.builtin.set_fact:
+ idrac_os_deployment_custom_iso_file: "{{ idrac_os_deployment_wd.path }}/{{ idrac_os_deployment_custom_iso_filename }}"
+
+- name: Create a extract directory in the working directory
+ register: idrac_os_deployment_create_extract_dir
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.file:
+ path: "{{ idrac_os_deployment_wd.path }}/{{ idrac_os_deployment_extract_dir }}"
+ state: directory
+ mode: "{{ idrac_os_deployment_iso_extract_dir_mode }}"
+
+- name: Set extracted directory path
+ ansible.builtin.set_fact:
+ idrac_os_deployment_iso_extract_dir: "{{ idrac_os_deployment_create_extract_dir.path }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/download_or_copy_source_files.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/download_or_copy_source_files.yml
new file mode 100644
index 000000000..0a0c1a919
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/download_or_copy_source_files.yml
@@ -0,0 +1,112 @@
+---
+- name: Download or copy the source iso
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ block:
+ - name: Download via http, https protocol
+ when: source.protocol in ['http', 'https']
+ block:
+ - name: Set the Download path for http https
+ when: source.protocol in ['http', 'https']
+ ansible.builtin.set_fact:
+ idrac_os_deployment_iso_path: "{{ source.protocol }}://{{ source.hostname }}{{ source.iso_path }}/{{ source.iso_name }}"
+
+ - name: Download iso from source using wget for http and https
+ register: idrac_os_deployment_wget_cmd_out
+ changed_when: idrac_os_deployment_wget_cmd_out.rc == 0
+ failed_when: idrac_os_deployment_wget_cmd_out.rc != 0
+ no_log: "{{ set_no_log }}" # to avoid printing username and password
+ ansible.builtin.command:
+ "{{ (idrac_os_deployment_wget_cmd | format(idrac_os_deployment_iso_path, idrac_os_deployment_wd.path))
+ + ('' if validate_certs else idrac_os_deployment_wget_cmd_vc)
+ + ((idrac_os_deployment_wget_cmd_creds | format(source.username, source.password)) if (source.username is defined) else '') }}"
+
+ - name: Set the iso file path
+ ansible.builtin.set_fact:
+ idrac_os_deployment_iso_file: "{{ idrac_os_deployment_wd.path }}/{{ source.iso_name }}"
+ idrac_os_deployment_success_message_os_deployment: "{{ idrac_os_deployment_success_message_os_deployment_iso }}"
+
+ - name: Copy the iso from local for protocol local, cifs, nfs
+ when: source.protocol in ['local', 'cifs', 'nfs']
+ block:
+ - name: Set the Download path for local, cifs, nfs
+ when: source.protocol in ['local', 'cifs', 'nfs']
+ ansible.builtin.set_fact:
+ idrac_os_deployment_iso_path: "{{ source.iso_path }}/{{ source.iso_name }}"
+
+ - name: Copy the iso from the local source
+ when: source.protocol in ['local', 'cifs', 'nfs']
+ ansible.builtin.copy:
+ src: "{{ idrac_os_deployment_iso_path }}"
+ dest: "{{ idrac_os_deployment_wd.path }}"
+ mode: "{{ idrac_os_deployment_src_copy_mode }}"
+ no_log: "{{ idrac_os_deployment_set_no_log }}"
+ register: idrac_os_deployment_iso_copy
+
+ - name: Set the iso file path
+ ansible.builtin.set_fact:
+ idrac_os_deployment_iso_file: "{{ idrac_os_deployment_iso_copy.dest }}"
+ idrac_os_deployment_success_message_os_deployment: "{{ idrac_os_deployment_success_message_os_deployment_iso }}"
+
+ rescue:
+ - name: Log error for source iso download
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_iso_file | format(idrac_os_deployment_iso_path) }}"
+
+- name: Download or copy the kickstart file
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ when: source.ks_path is defined and (source.is_custom_iso is undefined or source.is_custom_iso is false)
+ block:
+ - name: Download via http, https protocol
+ when: source.protocol in ['http', 'https']
+ block:
+ - name: Set the Download path for http, https
+ ansible.builtin.set_fact:
+ idrac_os_deployment_ks_path: "{{ source.protocol }}://{{ source.hostname }}{{ source.ks_path }}"
+
+ - name: Download ks from source using wget for http and https
+ register: idrac_os_deployment_wget_ks_cmd_out
+ changed_when: idrac_os_deployment_wget_ks_cmd_out.rc == 0
+ failed_when: idrac_os_deployment_wget_ks_cmd_out.rc != 0
+ no_log: "{{ set_no_log }}" # to avoid printing username and password
+ ansible.builtin.command:
+ "{{ (idrac_os_deployment_wget_cmd | format(idrac_os_deployment_ks_path, idrac_os_deployment_wd.path))
+ + ('' if validate_certs else idrac_os_deployment_wget_cmd_vc)
+ + ((idrac_os_deployment_wget_cmd_creds | format(source.username, source.password)) if (source.username is defined) else '') }}"
+
+ - name: Set the kickstart file path
+ ansible.builtin.set_fact:
+ idrac_os_deployment_kickstart_file: "{{ idrac_os_deployment_wd.path }}/{{ source.ks_path | basename }}"
+ idrac_os_deployment_success_message_os_deployment: "{{ idrac_os_deployment_success_message_os_deployment_ks }}"
+
+ - name: Copy from local for protocol local, cifs, nfs
+ when: source.protocol in ['local', 'cifs', 'nfs']
+ block:
+ - name: Set the Download path for local, cifs, nfs
+ ansible.builtin.set_fact:
+ idrac_os_deployment_ks_path: "{{ source.ks_path }}"
+
+ - name: Copy the kickstart from the local source
+ ansible.builtin.copy:
+ src: "{{ idrac_os_deployment_ks_path }}"
+ dest: "{{ idrac_os_deployment_wd.path }}"
+ mode: "{{ idrac_os_deployment_src_copy_mode }}"
+ no_log: "{{ idrac_os_deployment_set_no_log }}"
+ register: idrac_os_deployment_ks_copy
+
+ - name: Set the kickstart file path
+ ansible.builtin.set_fact:
+ idrac_os_deployment_kickstart_file: "{{ idrac_os_deployment_ks_copy.dest }}"
+ idrac_os_deployment_success_message_os_deployment: "{{ idrac_os_deployment_success_message_os_deployment_ks }}"
+
+ rescue:
+ - name: Log error for source kickstart download
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_ks_file | format(idrac_os_deployment_ks_path) }}"
+
+- name: Validate kickstart file path extension
+ when:
+ - source.ks_path is defined and (source.is_custom_iso is undefined or source.is_custom_iso is false)
+ - (idrac_os_deployment_kickstart_file | splitext | last) != ".cfg"
+ - idrac_os_deployment_validate_kickstart_file_ext is true
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_ks_file_ext | format(idrac_os_deployment_kickstart_file | splitext | last) }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/validate_inputs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/validate_inputs.yml
new file mode 100644
index 000000000..2e5ca7214
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/common/validate_inputs.yml
@@ -0,0 +1,74 @@
+---
+- name: Validate when custom iso if false
+ when: source.is_custom_iso is undefined or source.is_custom_iso is false
+ block:
+ - name: Validate the OS Name and OS version is provided
+ when: os_name is undefined or os_version is undefined
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_os_required }}"
+
+ - name: Validate the OS Name and OS version
+ when: (os_name | upper not in idrac_os_deployment_supported_os.keys()) or
+ ((os_version | string | split('.') | first) not in idrac_os_deployment_supported_os[os_name | upper])
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_unsupported_os | format(os_name, os_version) }}"
+
+ - name: Check if root password exists
+ when:
+ - source.ks_path is undefined
+ - ((os_name | upper == 'RHEL') and (rhel_rootpw | length == 0)) or
+ ((os_name | upper == 'ESXI') and (esxi_rootpw | length == 0))
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_root_password | format(os_name) }}"
+
+ - name: Check if the template file Exists
+ when: source.ks_path is undefined
+ block:
+ - name: Check if the template file exists
+ register: idrac_os_deployment_template_file
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.stat:
+ path: "{{ role_path }}/templates/{{ os_name | upper }}_{{ os_version | string | split('.') | first }}.j2"
+
+ - name: Fail if the Template file doesn't exists
+ when: not idrac_os_deployment_template_file.stat.exists
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_template | format(os_name | upper, os_version) }}"
+
+ - name: Validate destination required when custom iso is an input
+ when: destination is not defined
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_destination_required }}"
+
+ - name: Validate destination iso_name is not empty if provided
+ when:
+ - (destination is defined and destination.iso_name is defined and destination.iso_name == "")
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_destination_iso_name }}"
+
+ - name: Validate destination mountpath folder exists
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ when: destination is defined and destination.protocol in ['cifs','nfs']
+ block:
+ - name: Validate destination mountpath
+ register: idrac_os_deployment_mountpoint_folder
+ ansible.builtin.stat:
+ path: "{{ destination.mountpoint }}"
+
+ - name: Fail if the mountpoint destination doesn't exists
+ when: not idrac_os_deployment_mountpoint_folder.stat.exists
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_mountpoint_folder | format(destination.mountpoint) }}"
+
+- name: Validate when source is local custom iso is not true
+ when:
+ - (source.is_custom_iso is defined and source.is_custom_iso is true) and (source.protocol == "local")
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_custom_iso_local }}"
+
+- name: Validate hostname requirement for source
+ when:
+ - (source.hostname is undefined or source.hostname == "")
+ - (source.is_custom_iso is defined and source.is_custom_iso is true) or (source.protocol in ['http', 'https'])
+ ansible.builtin.fail:
+ msg: "{{ idrac_os_deployment_err_msg_hostname_required }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/esxi/compile_iso.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/esxi/compile_iso.yml
new file mode 100644
index 000000000..8555f1f8c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/esxi/compile_iso.yml
@@ -0,0 +1,37 @@
+---
+- name: Copy KS file to extracted directory
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.copy:
+ src: "{{ idrac_os_deployment_kickstart_file }}"
+ dest: "{{ idrac_os_deployment_iso_extract_dir }}/{{ idrac_os_deployment_esxi_ks_filename }}"
+ mode: "{{ idrac_os_deployment_copy_mode }}"
+
+- name: Append ks path to the linux boot menu
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.lineinfile:
+ path: "{{ item }}"
+ regexp: "^kernelopt="
+ line: "kernelopt=runweasel ks={{ idrac_os_deployment_esxi_ks_location }}"
+ with_items:
+ - "{{ idrac_os_deployment_iso_extract_dir }}/EFI/BOOT/BOOT.CFG"
+ - "{{ idrac_os_deployment_iso_extract_dir }}/BOOT.CFG"
+
+- name: Compile custom ISO
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.command:
+ cmd: "{{ idrac_os_deployment_esxi_mkiso_cmd | format(idrac_os_deployment_custom_iso_file, idrac_os_deployment_iso_extract_dir) }}"
+ register: idrac_os_deployment_mkisofs_output
+ changed_when: idrac_os_deployment_mkisofs_output.rc == 0
+ failed_when: idrac_os_deployment_mkisofs_output.rc != 0
+
+- name: Post-process ISO image with isohybrid
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.command: "{{ idrac_os_deployment_hybrid_cmd | format(idrac_os_deployment_custom_iso_file) }}"
+ register: idrac_os_deployment_isohybrid_output
+ changed_when: idrac_os_deployment_isohybrid_output.rc == 0
+
+- name: Add correct checksum to iso
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.command: "{{ idrac_os_deployment_checksum_cmd | format(idrac_os_deployment_custom_iso_file) }}"
+ register: idrac_os_deployment_checksum_output
+ changed_when: idrac_os_deployment_checksum_output.rc == 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/attach_iso_to_virtual_media.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/attach_iso_to_virtual_media.yml
new file mode 100644
index 000000000..8796cca17
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/attach_iso_to_virtual_media.yml
@@ -0,0 +1,43 @@
+---
+- name: Attach the iso image to idrac virtual media
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ block:
+ - name: Create virtual media mount facts
+ when: source.is_custom_iso is undefined or source.is_custom_iso is false
+ ansible.builtin.set_fact:
+ idrac_os_deployment_vm_protocol: "{{ destination.protocol }}"
+ idrac_os_deployment_vm_hostname: "{{ destination.hostname }}"
+ idrac_os_deployment_vm_iso_path: "{{ destination.iso_path }}"
+ idrac_os_deployment_vm_iso_name: "{{ idrac_os_deployment_custom_iso_filename }}"
+ idrac_os_deployment_vm_username: "{{ destination.username | default(omit) }}"
+ idrac_os_deployment_vm_password: "{{ destination.password | default(omit) }}"
+ no_log: "{{ set_no_log }}"
+
+ - name: Create virtual media mount url
+ when: idrac_os_deployment_vm_protocol
+ ansible.builtin.set_fact:
+ idrac_os_deployment_vm_url:
+ "{{ idrac_os_deployment_vm_proto_map[idrac_os_deployment_vm_protocol]
+ | format(idrac_os_deployment_vm_hostname, idrac_os_deployment_vm_iso_path, idrac_os_deployment_vm_iso_name) }}"
+
+ - name: Attach the iso to Virtual Media slot 1
+ register: idrac_os_deployment_vm_insert
+ dellemc.openmanage.idrac_virtual_media:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ timeout: "{{ https_timeout }}"
+ force: true
+ virtual_media:
+ - insert: true
+ image: "{{ idrac_os_deployment_vm_url }}"
+ username: "{{ idrac_os_deployment_vm_username | default(omit) }}"
+ password: "{{ idrac_os_deployment_vm_password | default(omit) }}"
+
+ - name: Set virtual media attached to success
+ when: idrac_os_deployment_vm_insert is succeeded
+ ansible.builtin.set_fact:
+ idrac_os_deployment_virtual_media_attached: true
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/clean_up_virtual_media_slot.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/clean_up_virtual_media_slot.yml
new file mode 100644
index 000000000..027fe5955
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/clean_up_virtual_media_slot.yml
@@ -0,0 +1,13 @@
+---
+- name: Eject the custom iso
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ dellemc.openmanage.idrac_virtual_media:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ timeout: "{{ https_timeout }}"
+ virtual_media:
+ - insert: false
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/set_boot_mode_and_restart.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/set_boot_mode_and_restart.yml
new file mode 100644
index 000000000..a14fecb7d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/idrac/set_boot_mode_and_restart.yml
@@ -0,0 +1,15 @@
+---
+- name: Configure the boot source override mode.
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ dellemc.openmanage.idrac_boot:
+ idrac_ip: "{{ hostname }}"
+ idrac_user: "{{ username }}"
+ idrac_password: "{{ password }}"
+ idrac_port: "{{ https_port }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ timeout: "{{ https_timeout }}"
+ boot_source_override_target: cd
+ boot_source_override_enabled: once
+ reset_type: force_restart
+ register: idrac_os_deployment_idrac_boot
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/extract_iso.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/extract_iso.yml
new file mode 100644
index 000000000..54e66a46e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/extract_iso.yml
@@ -0,0 +1,15 @@
+---
+- name: Extract the iso on to extract folder
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ register: idrac_os_deployment_extract_cmd_out
+ changed_when: idrac_os_deployment_extract_cmd_out.rc == 0
+ failed_when: idrac_os_deployment_extract_cmd_out.rc != 0
+ ansible.builtin.command: "{{ idrac_os_deployment_xorriso_cmd | format(idrac_os_deployment_iso_file, idrac_os_deployment_iso_extract_dir) }}"
+
+- name: Update file permissions
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.file:
+ path: "{{ idrac_os_deployment_iso_extract_dir }}"
+ state: directory
+ recurse: true
+ mode: "{{ idrac_os_deployment_iso_extract_dir_mode }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/generate_kickstart_file.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/generate_kickstart_file.yml
new file mode 100644
index 000000000..d3951ffc1
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/iso/generate_kickstart_file.yml
@@ -0,0 +1,15 @@
+---
+- name: Generate the Kickstart File
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ when: source.ks_path is undefined and (source.is_custom_iso is undefined or source.is_custom_iso is false)
+ block:
+ - name: Generate kickstart file
+ ansible.builtin.template:
+ src: "{{ os_name | upper }}_{{ os_version | string | split('.') | first }}.j2"
+ dest: "{{ idrac_os_deployment_wd.path }}/kickstart_{{ os_name }}_{{ hostname }}.cfg"
+ mode: "{{ idrac_os_deployment_ks_gen_mode }}"
+ register: idrac_os_deployment_ks_generate
+
+ - name: Set ks file for specific idrac
+ ansible.builtin.set_fact:
+ idrac_os_deployment_kickstart_file: "{{ idrac_os_deployment_ks_generate.dest }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/main.yml
new file mode 100644
index 000000000..9d636d562
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/main.yml
@@ -0,0 +1,74 @@
+---
+# tasks file for idrac_os_deployment
+- name: Operating system deployment on iDRAC
+ block:
+ - name: Validate the Inputs
+ ansible.builtin.include_tasks: common/validate_inputs.yml
+
+ - name: Create working directory , kickstart file and compile iso
+ when: source.is_custom_iso is undefined or source.is_custom_iso is false
+ block:
+ - name: Create working directory
+ ansible.builtin.include_tasks: common/create_working_directory_path.yml
+
+ - name: Download the Source iso
+ ansible.builtin.include_tasks: common/download_or_copy_source_files.yml
+
+ - name: Generate Kickstart file
+ when: source.ks_path is undefined
+ ansible.builtin.include_tasks: iso/generate_kickstart_file.yml
+
+ - name: Extract ISO
+ ansible.builtin.include_tasks: iso/extract_iso.yml
+
+ - name: Compile iso for the OS
+ ansible.builtin.include_tasks: "{{ os_name | lower }}/compile_iso.yml"
+
+ - name: Copy the iso to the destination
+ ansible.builtin.include_tasks: common/copy_iso_to_destination.yml
+
+ - name: Attach the Virtual Media to idrac
+ ansible.builtin.include_tasks: idrac/attach_iso_to_virtual_media.yml
+
+ - name: Set Boot Mode to once and restart the idrac
+ ansible.builtin.include_tasks: idrac/set_boot_mode_and_restart.yml
+
+ - name: Track for OS deployment
+ when: wait_for_os_deployment is true
+ ansible.builtin.include_tasks: tracking/track_for_os_deployment.yml
+
+ rescue:
+ - name: Set the failure messages
+ no_log: "{{ idrac_os_deployment_set_no_log }}"
+ ansible.builtin.set_fact:
+ idrac_os_deployment_failure: "{{ ansible_failed_result | combine({'failed_task_name': ansible_failed_task.name}) }}"
+
+ always:
+ - name: Clean up the Source and destination
+ when: source.is_custom_iso is undefined or source.is_custom_iso is false
+ block:
+ - name: Clean up the local directories
+ ansible.builtin.include_tasks: clean_up/clean_up_working_directory.yml
+
+ - name: Clean up the destination
+ when:
+ - wait_for_os_deployment is true and delete_custom_iso is true
+ - idrac_os_deployment_copied_to_destination is true
+ ansible.builtin.include_tasks: clean_up/clean_up_destinations.yml
+
+ - name: Clean up the virtual Media
+ when:
+ - wait_for_os_deployment is true and eject_iso is true
+ - idrac_os_deployment_virtual_media_attached is true
+ ansible.builtin.include_tasks: idrac/clean_up_virtual_media_slot.yml
+
+ - name: Report task failure
+ when: idrac_os_deployment_failure is defined
+ ansible.builtin.debug:
+ var: idrac_os_deployment_failure
+ failed_when: true
+
+ - name: Report operating system deployment success
+ when: idrac_os_deployment_failure is undefined and idrac_os_deployment_out != ""
+ ansible.builtin.debug:
+ var: idrac_os_deployment_out
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/rhel/compile_iso.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/rhel/compile_iso.yml
new file mode 100644
index 000000000..8091bba10
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/rhel/compile_iso.yml
@@ -0,0 +1,73 @@
+---
+- name: Copy KS to extracted
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.copy:
+ src: "{{ idrac_os_deployment_kickstart_file }}"
+ dest: "{{ idrac_os_deployment_iso_extract_dir }}/{{ idrac_os_deployment_rhel_ks_filename }}"
+ mode: "{{ idrac_os_deployment_copy_mode }}"
+
+- name: Append ks path to the linux boot menu
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.lineinfile:
+ path: "{{ item }}"
+ regexp: "^(.*inst.stage2=hd:LABEL.*?)( inst.ks={{ idrac_os_deployment_rhel_ks_location }})?$"
+ backrefs: true
+ firstmatch: true
+ line: '\1 inst.ks={{ idrac_os_deployment_rhel_ks_location }}'
+ with_items:
+ - "{{ idrac_os_deployment_iso_extract_dir }}/isolinux/isolinux.cfg"
+ - "{{ idrac_os_deployment_iso_extract_dir }}/EFI/BOOT/grub.cfg"
+
+- name: Menu default remove all occurrences
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.lineinfile:
+ path: "{{ idrac_os_deployment_iso_extract_dir }}/isolinux/isolinux.cfg"
+ search_string: "menu default"
+ state: absent
+
+- name: Menu default insert before kernel vmlinuz isolinux
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.lineinfile:
+ path: "{{ idrac_os_deployment_iso_extract_dir }}/isolinux/isolinux.cfg"
+ line: " menu default"
+ firstmatch: true
+ insertbefore: ".*kernel vmlinuz.*"
+
+- name: Grub menu default 0
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.lineinfile:
+ path: "{{ idrac_os_deployment_iso_extract_dir }}/EFI/BOOT/grub.cfg"
+ line: 'set default="0"'
+ firstmatch: true
+ regexp: "^set default="
+
+- name: Get iso LABEL
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.command: "blkid -s LABEL -o value {{ idrac_os_deployment_iso_file }}"
+ register: idrac_os_deployment_blkid_output
+ changed_when: idrac_os_deployment_blkid_output.rc != 0
+
+- name: Set iso LABEL
+ ansible.builtin.set_fact:
+ idrac_os_deployment_iso_label: "{{ idrac_os_deployment_blkid_output.stdout | trim }}"
+
+- name: Compile custom ISO
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.command:
+ chdir: "{{ idrac_os_deployment_iso_extract_dir }}"
+ cmd: "{{ idrac_os_deployment_rhel_mkiso_cmd | format(idrac_os_deployment_custom_iso_file, idrac_os_deployment_iso_label) }}"
+ register: idrac_os_deployment_mkisofs_output
+ changed_when: idrac_os_deployment_mkisofs_output.rc == 0
+ failed_when: idrac_os_deployment_mkisofs_output.rc != 0
+
+- name: Post-process ISO image with isohybrid
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.command: "{{ idrac_os_deployment_hybrid_cmd | format(idrac_os_deployment_custom_iso_file) }}"
+ register: idrac_os_deployment_isohybrid_output
+ changed_when: idrac_os_deployment_isohybrid_output.rc == 0
+
+- name: Add correct checksum to iso
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.command: "{{ idrac_os_deployment_checksum_cmd | format(idrac_os_deployment_custom_iso_file) }}"
+ register: idrac_os_deployment_checksum_output
+ changed_when: idrac_os_deployment_checksum_output.rc == 0
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/tracking/track_for_os_deployment.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/tracking/track_for_os_deployment.yml
new file mode 100644
index 000000000..358990874
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tasks/tracking/track_for_os_deployment.yml
@@ -0,0 +1,11 @@
+---
+- name: Wait for operating system intallation based on a wait time
+ delegate_to: "{{ idrac_os_deployment_delegate }}"
+ ansible.builtin.wait_for:
+ timeout: "{{ (os_deployment_timeout * 60) }}"
+
+- name: Set the Operating system success message
+ ansible.builtin.set_fact:
+ idrac_os_deployment_out: "{{ idrac_os_deployment_success_message_os_deployment }}"
+ changed_when: true
+ no_log: "{{ idrac_os_deployment_set_no_log }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/ESXI_8.j2 b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/ESXI_8.j2
new file mode 100644
index 000000000..67c338c58
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/ESXI_8.j2
@@ -0,0 +1,39 @@
+accepteula
+{% if esxi_keyboard is defined and esxi_keyboard != None %}
+keyboard "{{ esxi_keyboard }}"
+{% endif %}
+{% if esxi_iscrypted is defined and esxi_iscrypted == true %}
+rootpw {{ esxi_rootpw }} --iscrypted
+{% else %}
+rootpw {{ esxi_rootpw }}
+{% endif %}
+{{ ([esxi_install_type] + esxi_install_options)|join(' ') }}
+{% set esxicmds = {'clearpart': esxi_clearpart, 'network': esxi_network, 'partition': esxi_partition} %}
+{% for key,value in esxicmds.items() %}
+{% if value is defined and value != false %}
+{{ ([key] + value)|join(' ') }}
+{% endif %}
+{% endfor %}
+{% if esxi_serial_num is defined and esxi_serial_num != None %}
+serialnum --esx={{ esxi_serial_num }}
+{% endif %}
+{# boolean cmds #}
+{% set boolcmds = {'reboot': esxi_reboot, 'paranoid': esxi_paranoid, 'dryrun': esxi_dryrun} %}
+{% for key,value in boolcmds.items() %}
+{% if value is defined and value == true %}
+{{ key }}
+{% endif %}
+{% endfor %}
+{# scripts logic #}
+{% set scripts = {'pre': esxi_prescript, 'post': esxi_postscript, 'firstboot': esxi_firstboot} %}
+{% for key,value in scripts.items() %}
+{% if value is defined and value != None %}
+{% set xkey = value %}
+{% endif %}
+{% if xkey is defined and xkey.args != None %}
+%{{ key }} --interpreter={{ xkey.interpreter | default('busybox') }}
+{% for cmd in xkey.args %}
+{{ cmd }}
+{% endfor %}
+{% endif %}
+{% endfor %}
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_8.j2 b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_8.j2
new file mode 100644
index 000000000..de4903a08
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_8.j2
@@ -0,0 +1,31 @@
+eula --agreed
+lang {{ rhel_lang }}
+keyboard {{ rhel_keyboard }}
+timezone {{ rhel_timezone|join(' ') }}
+{% if rhel_iscrypted is defined and rhel_iscrypted == true %}
+rootpw {{ rhel_rootpw }} --iscrypted
+{% else %}
+rootpw {{ rhel_rootpw }} --plaintext
+{% endif %}
+{{ rhel_install_source }}
+bootloader --append="rhgb quiet crashkernel=auto" {{ rhel_bootloader|join(' ') }}
+{% if rhel_zerombr is defined and rhel_zerombr == true %}
+zerombr
+{% endif %}
+{% set my_dict = {'clearpart': rhel_clearpart, 'autopart': rhel_autopart, 'firstboot': rhel_firstboot,
+'network': rhel_network, 'firewall': rhel_firewall, 'selinux': rhel_selinux} %}
+{% for key,value in my_dict.items() %}
+{% if value is defined and value != false %}
+{{ ([key] + value)|join(' ') }}
+{% endif %}
+{% endfor %}
+{% if rhel_reboot is defined and rhel_reboot == true %}
+reboot
+{% endif %}
+{% if rhel_packages is defined and rhel_packages != false and rhel_packages != [] %}
+%packages
+{% for pkg in rhel_packages %}
+{{ pkg }}
+{% endfor %}
+%end
+{% endif %}
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_9.j2 b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_9.j2
new file mode 100644
index 000000000..0721986e0
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/templates/RHEL_9.j2
@@ -0,0 +1,31 @@
+eula --agreed
+lang {{ rhel_lang }}
+keyboard {{ rhel_keyboard }}
+timezone {{ rhel_timezone|join(' ') }}
+{% if rhel_iscrypted is defined and rhel_iscrypted == true %}
+rootpw {{ rhel_rootpw }} --iscrypted
+{% else %}
+rootpw {{ rhel_rootpw }} --plaintext
+{% endif %}
+{{ rhel_install_source }}
+bootloader --append="rhgb quiet crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M" {{ rhel_bootloader|join(' ') }}
+{% if rhel_zerombr is defined and rhel_zerombr == true %}
+zerombr
+{% endif %}
+{% set my_dict = {'clearpart': rhel_clearpart, 'autopart': rhel_autopart, 'firstboot': rhel_firstboot,
+'network': rhel_network, 'firewall': rhel_firewall, 'selinux': rhel_selinux} %}
+{% for key,value in my_dict.items() %}
+{% if value is defined and value != false %}
+{{ ([key] + value)|join(' ') }}
+{% endif %}
+{% endfor %}
+{% if rhel_reboot is defined and rhel_reboot == true %}
+reboot
+{% endif %}
+{% if rhel_packages is defined and rhel_packages != false and rhel_packages != [] %}
+%packages
+{% for pkg in rhel_packages %}
+{{ pkg }}
+{% endfor %}
+%end
+{% endif %}
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/inventory
new file mode 100644
index 000000000..7cfd90d39
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/inventory
@@ -0,0 +1,8 @@
+# For SSH into Linux
+192.168.0.2 ansible_ssh_user=user ansible_ssh_pass=password
+
+# For SSH into windows
+192.168.0.3 ansible_ssh_user=user ansible_ssh_pass=password ansible_remote_tmp="C:\\Users\\user\\tmp" become_method=runas ansible_shell_type=cmd shell_type=cmd
+
+[idrac]
+192.168.0.1
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/test.yml
new file mode 100644
index 000000000..568c6e4ce
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/tests/test.yml
@@ -0,0 +1,5 @@
+---
+- name: Operating System Deployment on iDRAC
+ hosts: idrac
+ roles:
+ - idrac_os_deployment
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/vars/main.yml
new file mode 100644
index 000000000..46220659d
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_os_deployment/vars/main.yml
@@ -0,0 +1,93 @@
+---
+# vars file for idrac_os_deployment
+idrac_os_deployment_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+# OS Supported values Validation
+idrac_os_deployment_supported_os:
+ RHEL: ["8", "9"]
+ ESXI: ["8"]
+
+# Validation Error messages
+idrac_os_deployment_err_msg_os_required: "The parameters `os_name` and `os_version` is required."
+idrac_os_deployment_err_msg_unsupported_os: "The combination of OS name %s and version %s is not supported."
+idrac_os_deployment_err_msg_destination_required: "Input parameter `destination` is required."
+idrac_os_deployment_err_msg_root_password: "Please provide the root password for %s."
+idrac_os_deployment_err_msg_custom_iso_local: "Custom iso as a source with local protocol is not supported."
+idrac_os_deployment_err_msg_hostname_required: "Source hostname is required when custom iso is true or when protocol is http/https."
+idrac_os_deployment_err_msg_template: "Template with the name %s_%s.j2 doesn't exists in templates."
+idrac_os_deployment_err_msg_kickstat_file: "Kickstart file does not exist or is not readable %s."
+idrac_os_deployment_err_msg_iso_file: "Download or Copy of ISO failed from the location %s,
+ Please check if iso file exists or credentials are correct and retry."
+idrac_os_deployment_err_msg_ks_file: "Download or Copy of Kickstart failed from the location %s,
+ Please check if iso file exists or credentials are correct and retry."
+idrac_os_deployment_err_msg_destination_iso_name: "In the destination `iso_name` cannot be empty,
+ please provide the value or remove the var to auto name the custom iso file."
+idrac_os_deployment_err_msg_ks_file_ext: "The kickstart file extension should be `.cfg`and cannot be `%s`."
+idrac_os_deployment_err_msg_mountpoint_folder: "The folder specfied `destination.mountpoint` : %s doesn't exists."
+
+# Success messages
+idrac_os_deployment_out: ""
+idrac_os_deployment_success_message_os_deployment: "Successfully deployed the Operating System with the given custom iso."
+idrac_os_deployment_success_message_os_deployment_ks: "Successfully deployed the Operating System with the given kickstart file."
+idrac_os_deployment_success_message_os_deployment_iso: "Successfully deployed the Operating System."
+
+# download wget command
+idrac_os_deployment_wget_cmd: "wget %s --directory-prefix=%s"
+idrac_os_deployment_wget_cmd_vc: " --no-check-certificate"
+idrac_os_deployment_wget_cmd_creds: " --user=%s --password=%s"
+
+# Mode Settings
+idrac_os_deployment_src_copy_mode: "0744"
+idrac_os_deployment_copy_mode: "0744"
+idrac_os_deployment_iso_extract_dir_mode: "0755"
+idrac_os_deployment_dest_mode: "0755"
+idrac_os_deployment_ks_gen_mode: "0744"
+
+
+# temp directory settings
+idrac_os_deployment_extract_dir: extract
+idrac_os_deployment_temp_file_prefix: "omam_osd"
+
+# Attributes required to compile iso
+idrac_os_deployment_kickstart_file: ""
+idrac_os_deployment_iso_file: ""
+idrac_os_deployment_iso_extract_dir: ""
+idrac_os_deployment_custom_iso_filename: "{{ hostname }}_{{ source.iso_name }}"
+idrac_os_deployment_custom_iso_file: ""
+idrac_os_deployment_hybrid_cmd: isohybrid --uefi %s
+idrac_os_deployment_checksum_cmd: implantisomd5 %s
+idrac_os_deployment_xorriso_cmd: "xorriso -osirrox on -indev %s -extract / %s"
+
+# Attributes required to compile esxi iso
+idrac_os_deployment_esxi_ks_filename: "KS.CFG"
+idrac_os_deployment_esxi_ks_dest_prefix: "cdrom:/"
+idrac_os_deployment_esxi_ks_location: "{{ idrac_os_deployment_esxi_ks_dest_prefix }}{{ idrac_os_deployment_esxi_ks_filename }}"
+idrac_os_deployment_esxi_mkiso_cmd:
+ "mkisofs -relaxed-filenames -J -R -o %s -b ISOLINUX.BIN -c BOOT.CAT
+ -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot
+ -eltorito-platform efi -b EFIBOOT.IMG -no-emul-boot %s"
+
+# Attributes required to compile rhel iso
+idrac_os_deployment_rhel_ks_filename: "ks.cfg"
+idrac_os_deployment_rhel_ks_dest_prefix: "cdrom:/"
+idrac_os_deployment_rhel_ks_location: "{{ idrac_os_deployment_rhel_ks_dest_prefix }}{{ idrac_os_deployment_rhel_ks_filename }}"
+idrac_os_deployment_rhel_mkiso_cmd:
+ "mkisofs -o %s -b isolinux/isolinux.bin -J -R -l -c isolinux/boot.cat
+ -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e images/efiboot.img
+ -no-emul-boot -graft-points -joliet-long -V %s ."
+
+# Extra params
+idrac_os_deployment_set_no_log: false
+idrac_os_deployment_validate_kickstart_file_ext: true
+idrac_os_deployment_copied_to_destination: false
+idrac_os_deployment_virtual_media_attached: false
+idrac_os_deployment_vm_protocol: "{{ source.protocol }}"
+idrac_os_deployment_vm_hostname: "{{ source.hostname }}"
+idrac_os_deployment_vm_iso_path: "{{ source.iso_path }}"
+idrac_os_deployment_vm_iso_name: "{{ source.iso_name }}"
+idrac_os_deployment_vm_username: "{{ source.username }}"
+idrac_os_deployment_vm_password: "{{ source.password }}"
+idrac_os_deployment_vm_proto_map:
+ http: "http://%s%s/%s"
+ https: "https://%s%s/%s"
+ cifs: "//%s%s/%s"
+ nfs: "%s:%s/%s"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_reset/README.md
new file mode 100644
index 000000000..f45c6154c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/README.md
@@ -0,0 +1,180 @@
+# idrac_reset
+
+Role to reset and restart iDRAC (iDRAC8 and iDRAC9 only) for Dell PowerEdge servers.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>wait_for_idrac</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Wait for the iDRAC to restart and LC status to be ready.<br>- When I(reset_to_default) is C(All), the IP address of iDRAC might not be accessible because of the change in network settings.<br>- When I(reset_to_default) is C(ResetAllWithRootDefaults), the IP address of iDRAC might not be accessible because of the change in network settings.</td>
+ </tr>
+ <tr>
+ <td>force_reset</td>
+ <td>false</td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Force restart the idrac without checking the idrac lifecycle controller status.</td>
+ </tr>
+ <tr>
+ reset_to_default:
+ <td>reset_to_default</td>
+ <td>false</td>
+ <td></td>
+ <td>["All", "ResetAllWithRootDefaults", "Default"]</td>
+ <td>str</td>
+ <td>- Reset the iDRAC to factory default settings.<br>- If this value is not set, then the default behaviour is to restart the iDRAC.<br>- C(All)This action will reset your iDRAC to the factory defaults. SupportAssist settings including registration information will be permanently removed. Username and password will reset to default credentials.<br>- C(ResetAllWithRootDefaults)This action will reset your iDRAC to the factory defaults. SupportAssist settings including registration information will be permanently removed. Default username will reset to root and password to the shipping value (root/shipping value).<br>- C(Default)This action will reset your iDRAC to the factory defaults. SupportAssist settings including registration information will be permanently removed. User and network settings will be preserved.<br>- "Note: Supported only for iDRAC9."</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_reset_out</td>
+ <td>{"msg": "iDRAC reset operation completed successfully"
+}</td>
+<td>Module output of idrac reset</td>
+</tbody>
+</table>
+
+## Examples
+-----
+
+```
+- name: Restart the idrac and wait for the idrac to be ready
+ ansible.builtin.include_role:
+ name: idrac_reset
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+
+- name: Restart the idrac and do not wait for the idrac to be ready
+ ansible.builtin.include_role:
+ name: idrac_reset
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ wait_for_idrac: false
+
+- name: Reset the idrac and wait for the idrac to be ready
+ ansible.builtin.include_role:
+ name: idrac_reset
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ reset_to_default: "All"
+```
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Kritika Bhateja (Kritika.Bhateja@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/defaults/main.yml
new file mode 100644
index 000000000..2f93da03a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+# defaults file for idrac_reset
+validate_certs: true
+https_timeout: 30
+https_port: 443
+wait_for_idrac: true
+force_reset: false
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/handlers/main.yml
new file mode 100644
index 000000000..22f42c01c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_reset
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/argument_specs.yml
new file mode 100644
index 000000000..f9f62c933
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/argument_specs.yml
@@ -0,0 +1,70 @@
+---
+argument_specs:
+ main:
+ version_added: "7.6.0"
+ short_description: Role to reset and restart iDRAC
+ description:
+ - Role to reset and restart iDRAC (iDRAC8 and iDRAC9 only) for Dell PowerEdge servers.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address or hostname.
+ username:
+ type: str
+ description: iDRAC username with admin privileges.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The HTTPS socket level timeout in seconds.
+ type: int
+ default: 30
+ wait_for_idrac:
+ description:
+ - Wait for the iDRAC to restart and LC status to be ready.
+ - When I(reset_to_default) is C(All), the IP address of iDRAC might not be accessible because of the change in network settings.
+ - When I(reset_to_default) is C(ResetAllWithRootDefaults), the IP address of iDRAC might not be accessible because of the change in network settings.
+ type: bool
+ default: true
+ force_reset:
+ description:
+ - Force restart the idrac without checking the idrac lifecycle controller status.
+ type: bool
+ default: false
+ reset_to_default:
+ description:
+ - Reset the iDRAC to factory default settings.
+ - If this value is not set, then the default behaviour is to restart the iDRAC.
+ - C(All)This action will reset your iDRAC to the factory defaults. SupportAssist settings including registration
+ information will be permanently removed.
+ Username and password will reset to default credentials.
+ - C(ResetAllWithRootDefaults)This action will reset your iDRAC to the factory defaults. SupportAssist settings including
+ registration information will be permanently removed.
+ Default username will reset to root and password to the shipping
+ value (root/shipping value).
+ - C(Default)This action will reset your iDRAC to the factory defaults. SupportAssist settings including registration
+ information will be permanently removed.
+ User and network settings will be preserved.
+ - "Note: Supported only for iDRAC9."
+ type: str
+ choices:
+ [
+ "All",
+ "ResetAllWithRootDefaults",
+ "Default",
+ ]
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/main.yml
new file mode 100644
index 000000000..4cd791f50
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/meta/main.yml
@@ -0,0 +1,25 @@
+galaxy_info:
+ role_name: idrac_reset
+ author: "Kritika Bhateja"
+ description: The role helps to reset and restart iDRAC.
+ company: Dell Technologies
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.13"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/lcstatus_check.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/lcstatus_check.yml
new file mode 100644
index 000000000..cd73a8d26
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/lcstatus_check.yml
@@ -0,0 +1,95 @@
+- name: Setting idrac_lc_status to default
+ ansible.builtin.set_fact:
+ idrac_lc_status:
+ LCStatus: ""
+
+- name: Get lifecycle controller status
+ when: idrac_lc_status.LCStatus != 'Ready'
+ block:
+ - name: Increment the retry
+ ansible.builtin.set_fact:
+ retry_count: "{{ 1 if retry_count is undefined else retry_count | int + 1 }}"
+
+ - name: Add a delay
+ ansible.builtin.pause:
+ seconds: "{{ idrac_reset_delay }}"
+
+ - name: Check whether lifecycle controller status is ready or not for iDRAC9
+ when:
+ - idrac_reset_fwm_ver is version('3.0', '>=')
+ block:
+ - name: Get lifecycle controller status for iDRAC9
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ idrac_reset_lifecycle_status_api }}"
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password |
+ default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers: "{{ idrac_reset_uri_headers }}"
+ body_format: "{{ idrac_reset_uri_body_format }}"
+ return_content: "{{ idrac_reset_uri_return_content }}"
+ force_basic_auth: "{{ idrac_reset_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ method: "POST"
+ body: "{}"
+ status_code: 200
+ delegate_to: "{{ idrac_reset_task_delegate }}"
+ register: result
+ ignore_errors: true
+
+ - name: Parse lifecycle controller status response
+ ansible.builtin.set_fact:
+ idrac_lc_status:
+ LCStatus: "{{ result.json.LCStatus }}"
+ RTStatus: "{{ result.json.RTStatus }}"
+ ServerStatus: "{{ result.json.ServerStatus }}"
+ Status: "{{ result.json.Status }}"
+
+ - name: Check whether lifecycle controller status is ready or not for iDRAC8
+ when:
+ - idrac_reset_fwm_ver is version('3.0', '<')
+ block:
+ - name: Check whether lifecycle controller status is ready or not
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}/wsman"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ method: POST
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password |
+ default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ headers: "{{ idrac_reset_uri_headers_xml }}"
+ body: "{{ lookup('ansible.builtin.template', 'idrac_lifecycle_controller_status.j2') }}"
+ status_code: 200
+ return_content: "{{ idrac_reset_uri_return_content }}"
+ force_basic_auth: "{{ idrac_reset_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ register: wsman_envelope_for_idrac_lc_status
+ delegate_to: "{{ idrac_reset_task_delegate }}"
+
+ - name: Parse lifecycle controller status response
+ ansible.builtin.set_fact:
+ idrac_lc_status: "{{ idrac_lc_status | default({}) | combine({item.key: idrac_reset_get_remote_services_api_status_code[item.key][item.value]}) }}"
+ with_dict:
+ LCStatus: "{{ wsman_envelope_for_idrac_lc_status.content | trim | regex_findall('(?<=<n1:LCStatus>).*(?=</n1:LCStatus>)') | first }}"
+ when: wsman_envelope_for_idrac_lc_status.content is search(".*<n1:ReturnValue>0</n1:ReturnValue>.*")
+
+ - name: Checking lifecycle controller status
+ ansible.builtin.fail:
+ msg: "Failed to get lifecycle controller status"
+ when: wsman_envelope_for_idrac_lc_status.content is search(".*<n1:ReturnValue>2</n1:ReturnValue>.*")
+ rescue:
+ - name: Maximum retries reached
+ ansible.builtin.fail:
+ msg: "LC status check is {{ idrac_lc_status.LCStatus }} after {{ retry_count }} number of retries, Exiting.."
+ when: (retry_count | int == idrac_reset_retries) and (idrac_lc_status.LCStatus != "Ready")
+
+ - name: Log the LC status
+ ansible.builtin.debug:
+ msg: "LC Status is Ready"
+ when: (retry_count | int <= idrac_reset_retries) and (idrac_lc_status.LCStatus == "Ready")
+
+ - name: Call LC Status Check
+ ansible.builtin.include_tasks: lcstatus_check.yml
+ when: (retry_count | int < idrac_reset_retries) or (idrac_lc_status.LCStatus != "Ready")
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/main.yml
new file mode 100644
index 000000000..72deb9d61
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tasks/main.yml
@@ -0,0 +1,146 @@
+---
+- name: Check whether atleast one of 'IDRAC_USERNAME' or username is provided
+ ansible.builtin.fail:
+ msg: "Ensure the value for environment variable 'IDRAC_USERNAME' or
+ the argument 'username' is set."
+ when: username is not defined and not lookup('env', 'IDRAC_USERNAME')
+
+- name: Check whether atleast one of 'IDRAC_PASSWORD' or password is provided
+ ansible.builtin.fail:
+ msg: "Ensure the value for environment variable 'IDRAC_PASSWORD' or
+ the argument 'password' is set."
+ when: password is not defined and not lookup('env', 'IDRAC_PASSWORD')
+
+- name: Setting uri options
+ ansible.builtin.set_fact:
+ idrac_opts: &idrac_opts
+ user: "{{ username | default(lookup('env', 'IDRAC_USERNAME')) }}"
+ password: "{{ password | default(lookup('env', 'IDRAC_PASSWORD')) }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ headers: "{{ idrac_reset_uri_headers }}"
+ body_format: "{{ idrac_reset_uri_body_format }}"
+ return_content: "{{ idrac_reset_uri_return_content }}"
+ force_basic_auth: "{{ idrac_reset_force_basic_auth }}"
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+- name: Get connection
+ ansible.builtin.uri:
+ <<: *idrac_opts
+ url: "https://{{ hostname }}:{{ https_port }}/redfish/v1/Systems"
+ method: "GET"
+ status_code: "{{ idrac_reset_uri_status_code }}"
+ register: idrac_reset_connection
+ delegate_to: "{{ idrac_reset_task_delegate }}"
+
+- name: Validate hostname or certificate.
+ ansible.builtin.fail:
+ msg: "{{ idrac_reset_connection.msg }}"
+ when: idrac_reset_connection.status == -1
+
+- name: Validate credentials.
+ ansible.builtin.fail:
+ msg: "{{ idrac_reset_invalid_creds }}"
+ when: idrac_reset_connection.status == 401
+
+- name: Get the manager firmware version
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}/redfish/v1/Managers/iDRAC.Embedded.1"
+ <<: *idrac_opts
+ method: GET
+ register: idrac_reset_firmware_version
+ delegate_to: "{{ idrac_reset_task_delegate }}"
+
+- name: Set manager firmware version
+ ansible.builtin.set_fact:
+ idrac_reset_fwm_ver: "{{ idrac_reset_firmware_version.json.FirmwareVersion }}"
+
+- name: Check LC status
+ ansible.builtin.include_tasks: lcstatus_check.yml
+
+- name: Perform graceful restart operation
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ idrac_reset_graceful_restart_api }}"
+ <<: *idrac_opts
+ method: "POST"
+ body: '{"ResetType": "GracefulRestart"}'
+ status_code: 204
+ register: idrac_reset_restart_result
+ delegate_to: "{{ idrac_reset_task_delegate }}"
+ when: reset_to_default is not defined
+
+- name: Perform reset operation
+ ansible.builtin.uri:
+ url: "https://{{ hostname }}:{{ https_port }}{{ idrac_reset_reset_api }}"
+ <<: *idrac_opts
+ method: "POST"
+ body: '{"ResetType": "{{ reset_to_default }}" }'
+ status_code: [200, 405]
+ register: idrac_reset_result
+ delegate_to: "{{ idrac_reset_task_delegate }}"
+ when: reset_to_default is defined
+ ignore_errors: true
+
+- name: Message out the iDRAC 8 support for reset operation
+ ansible.builtin.debug:
+ msg: "iDRAC reset operations are not supported"
+ when:
+ - idrac_reset_result is not skipped and idrac_reset_result is defined
+ - idrac_reset_result.status is defined
+ - idrac_reset_result.status == 405
+
+- name: Check for iDRAC connection
+ when: (idrac_reset_result is not skipped and idrac_reset_result.status == 200)
+ or (idrac_reset_restart_result is not skipped and idrac_reset_restart_result.status == 204)
+ block:
+ - name: Wait for port 443 to become open on the host
+ ansible.builtin.wait_for:
+ host: "{{ hostname }}"
+ port: "{{ https_port }}"
+ delay: "{{ idrac_reset_delay_for_idrac_connection }}"
+ timeout: "{{ idrac_reset_wait_for_idrac_reachable }}"
+ connect_timeout: "{{ idrac_reset_connect_timeout }}"
+ sleep: "{{ idrac_reset_sleep_interval }}"
+ active_connection_states:
+ - "ESTABLISHED"
+ when:
+ - wait_for_idrac is true
+ delegate_to: "{{ idrac_reset_task_delegate }}"
+ register: idrac_reset_connection_status
+ ignore_errors: true
+
+ - name: Check LC status after restart/reset operation
+ ansible.builtin.include_tasks: lcstatus_check.yml
+ when:
+ - wait_for_idrac is true
+
+ - name: Set fact when restart is triggered successfully
+ ansible.builtin.set_fact:
+ idrac_reset_out: {msg: "{{ idrac_reset_restart_trigger }}"}
+ when:
+ - wait_for_idrac is false
+ - idrac_reset_restart_result is not skipped and idrac_reset_restart_result.status == 204
+
+ - name: Set fact when reset is triggered successfully
+ ansible.builtin.set_fact:
+ idrac_reset_out: {msg: "{{ idrac_reset_reset_trigger }}"}
+ when:
+ - wait_for_idrac is false
+ - idrac_reset_result is not skipped and idrac_reset_result.status == 200
+
+ - name: Set fact when restart is done successfully
+ ansible.builtin.set_fact:
+ idrac_reset_out: {msg: "{{ idrac_reset_idrac_restarted_success }}"}
+ when:
+ - wait_for_idrac is true
+ - idrac_reset_connection_status is not failed
+ - idrac_reset_restart_result is not skipped and idrac_reset_restart_result.status == 204
+
+ - name: Set fact when reset is done successfully
+ ansible.builtin.set_fact:
+ idrac_reset_out: {msg: "{{ idrac_reset_success }}"}
+ when:
+ - wait_for_idrac is true
+ - idrac_reset_connection_status is not failed
+ - idrac_reset_result is not skipped and idrac_reset_result.status == 200
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/templates/idrac_lifecycle_controller_status.j2 b/ansible_collections/dellemc/openmanage/roles/idrac_reset/templates/idrac_lifecycle_controller_status.j2
new file mode 100644
index 000000000..f79aacb6a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/templates/idrac_lifecycle_controller_status.j2
@@ -0,0 +1,23 @@
+<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:n1="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_LCService">
+ <s:Header>
+ <wsa:To s:mustUnderstand="true">https://{{ hostname }}:{{ https_port }}/wsman</wsa:To>
+ <wsman:ResourceURI s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_LCService</wsman:ResourceURI>
+ <wsa:ReplyTo>
+ <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
+ </wsa:ReplyTo>
+ <wsa:Action s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_LCService/GetRemoteServicesAPIStatus</wsa:Action>
+ <wsman:MaxEnvelopeSize s:mustUnderstand="true">524288</wsman:MaxEnvelopeSize>
+ <wsa:MessageID s:mustUnderstand="true">urn:uuid:{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=32') | to_uuid }}</wsa:MessageID>
+ <wsman:OperationTimeout>PT12.0S</wsman:OperationTimeout>
+ <wsman:SelectorSet>
+ <wsman:Selector Name="__cimnamespace">root/dcim</wsman:Selector>
+ <wsman:Selector Name="SystemName">DCIM:ComputerSystem</wsman:Selector>
+ <wsman:Selector Name="SystemCreationClassName">DCIM_ComputerSystem</wsman:Selector>
+ <wsman:Selector Name="Name">DCIM:LCService</wsman:Selector>
+ <wsman:Selector Name="CreationClassName">DCIM_LCService</wsman:Selector>
+ </wsman:SelectorSet>
+ </s:Header>
+ <s:Body>
+ <n1:GetRemoteServicesAPIStatus_INPUT />
+ </s:Body>
+</s:Envelope> \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/test.yml
new file mode 100644
index 000000000..f1b5e6dff
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Testing for idrac rest
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_reset
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_reset/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_reset/vars/main.yml
new file mode 100644
index 000000000..88179c6d0
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_reset/vars/main.yml
@@ -0,0 +1,41 @@
+---
+# vars file for idrac_reset
+idrac_reset_uri_headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+idrac_reset_uri_headers_xml:
+ Content-Type: "application/xml"
+idrac_reset_uri_body_format: "json"
+idrac_reset_force_basic_auth: true
+idrac_reset_uri_status_code:
+ - 200
+ - 400
+ - 401
+ - 404
+ - -1
+idrac_reset_delay: 30
+idrac_reset_retries: 10
+idrac_reset_delay_for_idrac_connection: 60
+idrac_reset_wait_for_idrac_reachable: 360
+idrac_reset_connect_timeout: 10
+idrac_reset_sleep_interval: 5
+idrac_reset_uri_return_content: true
+idrac_reset_idrac_restarted_success: "iDRAC restart operation completed successfully"
+idrac_reset_success: "iDRAC reset operation completed successfully"
+idrac_reset_reset_trigger: "iDRAC reset operation triggered successfully"
+idrac_reset_restart_trigger: "iDRAC restart operation triggered successfully"
+idrac_reset_lifecycle_status_api: "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+idrac_reset_graceful_restart_api: "/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Manager.Reset"
+idrac_reset_reset_api: "/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/DellManager.ResetToDefaults"
+idrac_reset_get_remote_services_api_status_code:
+ LCStatus:
+ "0": "Ready"
+ "1": "Not Initialized"
+ "2": "Reloading Data"
+ "3": "Disabled"
+ "4": "In Recovery"
+ "5": "In Use"
+ "U": "Unknown"
+idrac_reset_task_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
+idrac_reset_invalid_creds: "The authentication credentials included with this request are missing or invalid."
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/README.md
new file mode 100644
index 000000000..ff4152bf5
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/README.md
@@ -0,0 +1,217 @@
+# idrac_server_powerstate
+
+Role to to manage the different power states of the specified device using iDRACs (iDRAC8 and iDRAC9 only) for Dell PowerEdge servers.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+```
+### Production
+Requirements to use the role.
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>resource_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The unique identifier of the device being managed.For example- U(https://<I(baseuri)>/redfish/v1/Systems/<I(resource_id)>).<br>- This option is mandatory for I(base_uri) with multiple devices.<br>- To get the device details, use the API U(https://<I(baseuri)>/redfish/v1/Systems).</td>
+ </tr>
+ <tr>
+ <td>reset_type</td>
+ <td>false</td>
+ <td>'On'</td>
+ <td>["ForceOff", "ForceOn", "ForceRestart", "GracefulRestart", "GracefulShutdown", "Nmi", "On", "PowerCycle", "PushPowerButton"]</td>
+ <td>str</td>
+ <td>- This option resets the device.<br>- If C(ForceOff), Turns off the device immediately.<br>- If C(ForceOn), Turns on the device immediately.<br>- If C(ForceRestart), Turns off the device immediately, and then restarts the device.<br>- If C(GracefulRestart), Performs graceful shutdown of the device, and then restarts the device.<br>- If C(GracefulShutdown), Performs a graceful shutdown of the device, and the turns off the device.<br>- If C(Nmi), Sends a diagnostic interrupt to the device. This is usually a non-maskable interrupt (NMI) on x86 device.<br>- If C(On), Turns on the device.<br>- If C(PowerCycle), Performs power cycle on the device.<br>- If C(PushPowerButton), Simulates the pressing of a physical power button on the device.<br>- When a power control operation is performed, which is not supported on the device, an error message is displayed with the list of operations that can be performed.</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>idrac_server_powerstate_out</td>
+ <td>{"changed": true,
+ "failed": false,
+ "msg": "Successfully performed the reset type operation 'GracefulRestart'."
+}</td>
+<td>Module output of the powercycle contol</td>
+</tbody>
+</table>
+
+## Examples
+-----
+
+```
+- name: "Performing force off operation"
+ ansible.builtin.include_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_type: "ForceOff"
+
+- name: "Performing power on operation"
+ ansible.builtin.include_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_type: "On"
+
+- name: "Performing graceful restart operation"
+ ansible.builtin.include_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_type: "GracefulRestart"
+
+- name: "Performing graceful shutdown operation"
+ ansible.builtin.include_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_type: "GracefulShutdown"
+
+- name: "Performing powercycle operation"
+ ansible.builtin.include_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_type: "PowerCycle"
+
+- name: "Performing push power button operation"
+ ansible.builtin.include_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_type: "PushPowerButton"
+
+- name: "Performing force restart operation"
+ ansible.builtin.include_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "192.1.2.1"
+ username: "username"
+ password: "password"
+ ca_path: "/path/to/ca_cert.pem"
+ reset_type: "ForceRestart"
+```
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Kritika Bhateja (Kritika.Bhateja@Dell.com) 2023 \ No newline at end of file
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/defaults/main.yml
new file mode 100644
index 000000000..9538ec0a9
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/defaults/main.yml
@@ -0,0 +1,6 @@
+---
+# defaults file for idrac_server_powerstate
+validate_certs: true
+https_timeout: 30
+reset_type: "On"
+https_port: 443
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/handlers/main.yml
new file mode 100644
index 000000000..032a5a52e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_server_powerstate
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/argument_specs.yml
new file mode 100644
index 000000000..642da3104
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/argument_specs.yml
@@ -0,0 +1,69 @@
+---
+argument_specs:
+ main:
+ version_added: "7.4.0"
+ short_description: Role to manage the different power states of the specified device
+ description:
+ - Role to manage the different power states of the specified device using iDRACs (iDRAC8 and iDRAC9 only) for Dell PowerEdge servers.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ username:
+ type: str
+ description: iDRAC username.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The HTTPS socket level timeout in seconds.
+ type: int
+ default: 30
+ resource_id:
+ description:
+ - The unique identifier of the device being managed.
+ - This option is mandatory for I(hostname) with multiple devices.
+ type: str
+ reset_type:
+ description:
+ - This option resets the device.
+ - If C(ForceOff), Turns off the device immediately.
+ - If C(ForceOn), Turns on the device immediately.
+ - If C(ForceRestart), Turns off the device immediately, and then restarts the device.
+ - If C(GracefulRestart), Performs graceful shutdown of the device, and then restarts the device.
+ - If C(GracefulShutdown), Performs a graceful shutdown of the device, and the turns off the device.
+ - If C(Nmi), Sends a diagnostic interrupt to the device. This is usually a non-maskable interrupt (NMI) on x86 device.
+ - If C(On), Turns on the device.
+ - If C(PowerCycle), Performs power cycle on the device.
+ - If C(PushPowerButton), Simulates the pressing of a physical power button on the device.
+ - When a power control operation is performed, which is not supported on the device,
+ an error message is displayed with the list of operations that can be performed.
+ type: str
+ default: "On"
+ choices:
+ [
+ "ForceOff",
+ "ForceOn",
+ "ForceRestart",
+ "GracefulRestart",
+ "GracefulShutdown",
+ "Nmi",
+ "On",
+ "PowerCycle",
+ "PushPowerButton"
+ ]
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/main.yml
new file mode 100644
index 000000000..e206309b7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/meta/main.yml
@@ -0,0 +1,54 @@
+galaxy_info:
+ author: Kritika-Bhateja
+ description: The role helps to manage the different power states of the specified device.
+ company: Dell Technologies
+
+ # 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.13"
+
+ # If this a Container Enabled role, provide the minimum Ansible Container version.
+ # min_ansible_container_version:
+
+ #
+ # Provide a list of supported platforms, and for each platform a list of versions.
+ # If you don't wish to enumerate all versions for a particular platform, use 'all'.
+ # To view available platforms and versions (or releases), visit:
+ # https://galaxy.ansible.com/api/v1/platforms/
+ #
+
+ 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.
+
+dependencies: []
+ # List your role dependencies here, one per line. Be sure to remove the '[]' above,
+ # if you add dependencies to this list.
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/converge.yml
new file mode 100644
index 000000000..27ec2fdff
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/converge.yml
@@ -0,0 +1,188 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Performing operation on the iDRAC device using default reset_type
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ resource_id: "System.Embedded.1"
+
+ - name: Asserting after performing opeartion using default reset_type
+ ansible.builtin.assert:
+ that: |-
+ ( idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'On'." )
+ or
+ ( idrac_server_powerstate_out.msg == "The device is already powered on." )
+
+ - name: Performing operation On the iDRAC with invalid resource_id
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ resource_id: "System.Embedded.0"
+ ignore_errors: true
+ register: idrac_server_powerstate_error_msg
+
+ - name: Asserting after performing opeartion with invalid resource_id
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Invalid device Id 'System.Embedded.0' is provided"
+ - not idrac_server_powerstate_out.changed
+
+ - name: Performing operation 'On' with invalid hostname
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "randomHostname"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ resource_id: "System.Embedded.1"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_server_powerstate_error_msg
+
+ - name: Asserting after performing opeartion with invalid hostname
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "<urlopen error [Errno -2] Name or service not known>" or
+ idrac_server_powerstate_out.msg == "<urlopen error Unable to resolve hostname or IP randomHostname:443.>"
+
+ - name: Performing operation 'On' with invalid username
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "WrongUsername123"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ resource_id: "System.Embedded.1"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_server_powerstate_error_msg
+
+ - name: Asserting after performing opeartion with invalid username
+ ansible.builtin.assert:
+ that:
+ - '"HTTP Error 401" in idrac_server_powerstate_out.msg'
+
+ - name: Performing operation 'On' with invalid password
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "WrongPassword@123"
+ validate_certs: false
+ resource_id: "System.Embedded.1"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_server_powerstate_error_msg
+
+ - name: Asserting after performing opeartion with invalid password
+ ansible.builtin.assert:
+ that: |-
+ ('"HTTP Error 401" in idrac_server_powerstate_out.msg')
+ or
+ ('"urlopen error timed out" in idrac_server_powerstate_out.msg')
+
+ - name: Performing operation 'On' with invalid validate_certs
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: 'someStringValue'
+ resource_id: "System.Embedded.1"
+ ignore_errors: true
+ ignore_unreachable: true
+ register: idrac_server_powerstate_error_msg
+
+ - name: Asserting after performing opeartion with invalid validate_certs
+ ansible.builtin.assert:
+ that:
+ - '"Valid booleans include" in idrac_server_powerstate_out.msg'
+
+ - name: Performing operation 'ForceOn' on iDRAC server
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: 'false'
+ reset_type: 'ForceOn'
+ resource_id: "System.Embedded.1"
+ ignore_errors: true
+ register: idrac_server_powerstate_error_msg
+
+ - name: Asserting after performing opeartion "ForceOn"
+ ansible.builtin.assert:
+ that:
+ - '"The target device does not support a force on operation." in idrac_server_powerstate_out.msg'
+
+ - name: Fetching all the resource_id using URI
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: uri_out
+ no_log: true
+
+ - name: Splitting the resource_id and picking last
+ ansible.builtin.set_fact:
+ idrac_server_powerstate_resource_id_list: "{{ [item['@odata.id'] | split('/') | last] + idrac_server_powerstate_resource_id_list | default([]) }}"
+ loop: "{{ uri_out.json.Members }}"
+
+ - name: Count resource_id
+ ansible.builtin.set_fact:
+ number_of_resource_id: "{{ idrac_server_powerstate_resource_id_list | length }}"
+
+ - name: Performing Operation 'On' without resource_id when iDRAC has secondary resource_id
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ resource_id: "{{ null | default(omit) }}"
+ when: number_of_resource_id > '1'
+
+ - name: Asserting after performing opeartion without resource_id when iDRAC has secondary resource_id
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Multiple devices exists in the system, but option 'resource_id' is not specified."
+ when: number_of_resource_id > '1'
+
+ - name: Performing Operation 'On' with valid secondary resource_id
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: 'On'
+ resource_id: "{{ resource_id_list[1] }}"
+ when: number_of_resource_id > '1'
+
+ - name: Asserting after performing opeartion with valid secondary resource_id
+ ansible.builtin.assert:
+ that: |-
+ ( idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'On'." )
+ or
+ ( idrac_server_powerstate_out.msg == "The device is already powered on." )
+ when: number_of_resource_id > '1'
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/molecule.yml
new file mode 100644
index 000000000..ccf982411
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/default/molecule.yml
@@ -0,0 +1,9 @@
+scenario:
+ test_sequence:
+ - dependency
+ - destroy
+ - syntax
+ - create
+ - converge
+ - cleanup
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/converge.yml
new file mode 100644
index 000000000..6900d9f3f
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/converge.yml
@@ -0,0 +1,69 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Pre-requisite - Server is Power On
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "On"
+ resource_id: "System.Embedded.1"
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing Power On operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: idrac_server_powerstate_out.changed # noqa: no-handler
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: Performing ForceOff on the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "ForceOff"
+ resource_id: "System.Embedded.1"
+
+ - name: Asserting ForceOff in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Fetching iDRAC server powerstate after performing ForceOff operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: idrac_server_powerstate_current_powerstate
+ until: idrac_server_powerstate_current_powerstate.json.PowerState == "Off"
+ retries: 10
+ delay: 30
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ no_log: true
+
+ - name: Asserting ForceOff
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'ForceOff'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+
+ - name: Asserting 'ForceOff' in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "The device is already powered off."
+ when: not ansible_check_mode and not idrac_server_powerstate_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forceoff/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/converge.yml
new file mode 100644
index 000000000..10c8fe48b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/converge.yml
@@ -0,0 +1,72 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Pre-requisite - Server is Power On
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "On"
+ resource_id: "System.Embedded.1"
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing Power On operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: idrac_server_powerstate_out.changed # noqa: no-handler
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: Performing ForceRestart on the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "ForceRestart"
+ resource_id: "System.Embedded.1"
+ tags: molecule-idempotence-notest
+
+ - name: Asserting ForceRestart in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing ForceRestart operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
+
+ - name: Fetching iDRAC server powerstate after performing ForceRestart operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: "Accept=application/json"
+ register: idrac_server_powerstate_current_powerstate
+ until: idrac_server_powerstate_current_powerstate.json.PowerState == "On"
+ retries: 10
+ delay: 30
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ no_log: true
+ tags: molecule-idempotence-notest
+
+ - name: Asserting ForceRestart
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'ForceRestart'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/forcerestart/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/converge.yml
new file mode 100644
index 000000000..df4635004
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/converge.yml
@@ -0,0 +1,72 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Pre-requisite - Server is Power On
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "On"
+ resource_id: "System.Embedded.1"
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing Power On operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: idrac_server_powerstate_out.changed # noqa: no-handler
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: Performing ForceRestart on the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "GracefulRestart"
+ resource_id: "System.Embedded.1"
+ tags: molecule-idempotence-notest
+
+ - name: Asserting GracefulRestart in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing GracefulRestart operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
+
+ - name: Fetching iDRAC server powerstate after performing GracefulRestart operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: idrac_server_powerstate_current_powerstate
+ until: idrac_server_powerstate_current_powerstate.json.PowerState == "On"
+ retries: 10
+ delay: 30
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ no_log: true
+ tags: molecule-idempotence-notest
+
+ - name: Asserting GracefulRestart
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'GracefulRestart'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulrestart/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/converge.yml
new file mode 100644
index 000000000..ff929b07e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/converge.yml
@@ -0,0 +1,63 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Pre-requisite - Server is Power On
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "On"
+ resource_id: "System.Embedded.1"
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing Power On operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: idrac_server_powerstate_out.changed # noqa: no-handler
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: Performing GracefulShutdown on the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "GracefulShutdown"
+ resource_id: "System.Embedded.1"
+
+ - name: Asserting GracefulShutdown in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Fetching iDRAC server powerstate after performing GracefulShutdown operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: idrac_server_powerstate_current_powerstate
+ until: idrac_server_powerstate_current_powerstate.json.PowerState == "Off"
+ retries: 10
+ delay: 30
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ no_log: true
+
+ - name: Asserting GracefulShutdown
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'GracefulShutdown'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/gracefulshutdown/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/converge.yml
new file mode 100644
index 000000000..254c0bbd4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/converge.yml
@@ -0,0 +1,72 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Pre-requisite - Server is Power On
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "On"
+ resource_id: "System.Embedded.1"
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing Power On operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: idrac_server_powerstate_out.changed # noqa: no-handler
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: Performing Nmi on the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "Nmi"
+ resource_id: "System.Embedded.1"
+ tags: molecule-idempotence-notest
+
+ - name: Asserting Nmi in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing Nmi operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
+
+ - name: Fetching iDRAC server powerstate after performing Nmi operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: idrac_server_powerstate_current_powerstate
+ until: idrac_server_powerstate_current_powerstate.json.PowerState == "On"
+ retries: 10
+ delay: 30
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ no_log: true
+ tags: molecule-idempotence-notest
+
+ - name: Asserting Nmi
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'Nmi'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/nmi/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/converge.yml
new file mode 100644
index 000000000..329fb5b73
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/converge.yml
@@ -0,0 +1,73 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Pre-requisite - Server is Power Off
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "ForceOff"
+ resource_id: "System.Embedded.1"
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing ForceOff operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
+
+ - name: Performing Power On operation the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "On"
+ resource_id: "System.Embedded.1"
+
+ - name: Asserting On in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing On operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+
+ - name: Fetching iDRAC server powerstate after performing On operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: idrac_server_powerstate_current_powerstate
+ until: idrac_server_powerstate_current_powerstate.json.PowerState == "On"
+ retries: 10
+ delay: 30
+ when: not ansible_check_mode
+ no_log: true
+
+ - name: Asserting 'On' in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'On'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+
+ - name: Asserting 'On' in idempotence mode
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "The device is already powered on."
+ when: not ansible_check_mode and not idrac_server_powerstate_out.changed
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/on/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/converge.yml
new file mode 100644
index 000000000..074df5c99
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/converge.yml
@@ -0,0 +1,72 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Pre-requisite - Server is Power On
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "On"
+ resource_id: "System.Embedded.1"
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing Power On operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: idrac_server_powerstate_out.changed # noqa: no-handler
+ check_mode: false
+ tags: molecule-idempotence-notest
+
+ - name: Performing PowerCycle on the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "PowerCycle"
+ resource_id: "System.Embedded.1"
+ tags: molecule-idempotence-notest
+
+ - name: Asserting PowerCycle in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing PowerCycle operation"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
+
+ - name: Fetching iDRAC server powerstate after performing PowerCycle operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: idrac_server_powerstate_current_powerstate
+ until: idrac_server_powerstate_current_powerstate.json.PowerState == "On"
+ retries: 10
+ delay: 30
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ no_log: true
+ tags: molecule-idempotence-notest
+
+ - name: Asserting PowerCycle
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'PowerCycle'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/powercycle/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/converge.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/converge.yml
new file mode 100644
index 000000000..a4b430570
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/converge.yml
@@ -0,0 +1,48 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ idrac_server_powerstate_wait_seconds: "{{ lookup('env', 'idrac_powercycle_wait_seconds') }}"
+ tasks:
+ - name: Performing PushPowerButton on the iDRAC device
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "PushPowerButton"
+ resource_id: "System.Embedded.1"
+ tags: molecule-idempotence-notest
+
+ - name: Fetching iDRAC server powerstate after performing PushPowerButton operation
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}:{{ https_port }}/redfish/v1/Systems/System.Embedded.1"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ headers: 'Accept=application/json'
+ register: idrac_server_powerstate_current_powerstate
+ no_log: true
+ tags: molecule-idempotence-notest
+
+ - name: "Waiting after performing PushPowerButton operation, Server is Powering On"
+ ansible.builtin.pause:
+ seconds: "{{ idrac_server_powerstate_wait_seconds }}"
+ when: not ansible_check_mode and idrac_server_powerstate_current_powerstate.json.PowerState == "On"
+ tags: molecule-idempotence-notest
+
+ - name: Asserting PushPowerButton in check mode
+ ansible.builtin.assert:
+ that: idrac_server_powerstate_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+ tags: molecule-idempotence-notest
+
+ - name: Asserting PushPowerButton in normal mode
+ ansible.builtin.assert:
+ that:
+ - idrac_server_powerstate_out.msg == "Successfully performed the reset type operation 'PushPowerButton'."
+ when: not ansible_check_mode and idrac_server_powerstate_out.changed
+ tags: molecule-idempotence-notest
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/molecule.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/molecule/pushpowerbutton/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/init.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/init.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/init.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/main.yml
new file mode 100644
index 000000000..1d7b315eb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tasks/main.yml
@@ -0,0 +1,18 @@
+---
+# tasks file for idrac_server_powerstate
+- name: Setting up parameters
+ ansible.builtin.set_fact:
+ baseuri: "{{ hostname }}:{{ https_port }}"
+
+- name: "Performing the operation on iDRAC server: {{ reset_type }}"
+ dellemc.openmanage.redfish_powerstate:
+ baseuri: "{{ baseuri }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ timeout: "{{ https_timeout }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ reset_type: "{{ reset_type }}"
+ validate_certs: "{{ validate_certs }}"
+ resource_id: "{{ resource_id | default(omit) }}"
+ register: idrac_server_powerstate_out
+ delegate_to: "{{ idrac_server_powerstate_task_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/test.yml
new file mode 100644
index 000000000..89d986b52
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Executing iDRAC powercycle control role
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_server_powerstate
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/vars/main.yml
new file mode 100644
index 000000000..d571323bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_server_powerstate/vars/main.yml
@@ -0,0 +1,3 @@
+---
+# vars file for idrac_server_powerstate
+idrac_server_powerstate_task_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/README.md b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/README.md
new file mode 100644
index 000000000..2a9913839
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/README.md
@@ -0,0 +1,682 @@
+# idrac_storage_controller
+
+Role to configure the physical disk, virtual disk, and storage controller settings on iDRAC9 based PowerEdge servers.
+
+## Requirements
+
+### Development
+Requirements to develop and contribute to the role.
+```
+ansible
+docker
+molecule
+python
+```
+
+### Production
+Requirements to use the role.
+```
+ansible
+python
+```
+
+### Ansible collections
+Collections required to use the role
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>controller_id</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The ID of the controller on which the operations need to be performed.</td>
+ </tr>
+ <tr>
+ <td>volumes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- List of volume that belongs to I(controller_id).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Fully Qualified Device Descriptor (FQDD) of the volume.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dedicated_hot_spare</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Fully Qualified Device Descriptor (FQDD) of the physical disk to assign the volume as a dedicated hot spare to a disk.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;encrypted</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- To encrypt the virtual disk.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expand_capacity_disk</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Fully Qualified Device Descriptor (FQDD) of the disk for expanding the capacity with the existing disk.<br>- I(expand_capacity_size) is mutually exclusive with I(expand_capacity_disk).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expand_capacity_size</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Capacity of the virtual disk to be expanded in MB.<br>- Check mode and Idempotency is not supported for I(expand_capacity_size).<br>- Minimum Online Capacity Expansion size must be greater than 100 MB of the current size.<br>- I(expand_capacity_disk) is mutually exclusive with I(expand_capacity_size).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;blink</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Blinks the target virtual disk, and it always reports as changes found when check mode is enabled.</td>
+ </tr>
+ <tr>
+ <td>disks</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- List of physical disks that belongs to I(controller_id).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Fully Qualified Device Descriptor (FQDD) of the physical disk.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;blink</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Blinks the target physical disk, and it always reports as changes found when check mode is enabled.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raid_state</td>
+ <td>false</td>
+ <td></td>
+ <td>'raid', 'nonraid'</td>
+ <td>str</td>
+ <td>- Converts the disk form Non-Raid to Raid and vice versa.<br>- C(raid) converts the physical disk to Raid.<br>- C(nonraid) converts the physical disk to Non Raid.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status</td>
+ <td>false</td>
+ <td></td>
+ <td>'online', 'offline'</td>
+ <td>str</td>
+ <td>- Converts the disk form online to offline and vice versa.<br>- C(online) converts the physical disk status to online.<br>- C(offline) converts the physical disk status to offline.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;global_hot_spare</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Assigns a global hot spare or unassigns a hot spare.<br>- C(true) assigns the disk as a global hot spare.<br>- C(false) unassigns the disk as a hot spare.</td>
+ </tr>
+ <tr>
+ <td>reset_config</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- To reset the controller.</td>
+ </tr>
+ <tr>
+ <td>set_controller_key</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Set the security key or enable controller encryption.<br>- If I(mode) is provided controller encryption operation is performed, otherwise sets the controller security key.<br>- I(key), and I(key_id) are required for this operation.</td>
+ </tr>
+ <tr>
+ <td>rekey</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Resets the key on the controller, and it always reports as changes found when check mode is enabled.</td>
+ </tr>
+ <tr>
+ <td>remove_key</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Remove the key on controllers.</td>
+ </tr>
+ <tr>
+ <td>key</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- A new security key passphrase that the encryption-capable controller uses to create the encryption key. The controller uses the encryption key to lock or unlock access to the Self-Encrypting Drive (SED). Only one encryption key can be created for each controller.<br>- This is mandatory when I(set_controller_key) is C(true), I(rekey) is C(true).<br>- The length of the key can be a maximum of 32 characters in length, where the expanded form of the special character is counted as a single character.<br>- The key must contain at least one character from each of the character classes are uppercase, lowercase, number, and special character.</td>
+ </tr>
+ <tr>
+ <td>key_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- This is a user supplied text label associated with the passphrase.<br>- This is mandatory when I(set_controller_key) is C(true), I(rekey) is C(true).<br>- The length of I(key_id) can be a maximum of 32 characters in length and should not have any spaces.</td>
+ </tr>
+ <tr>
+ <td>old_key</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Security key passphrase used by the encryption-capable controller.<br>- This option is mandatory when I(rekey) is C(true).</td>
+ </tr>
+ <tr>
+ <td>mode</td>
+ <td>false</td>
+ <td></td>
+ <td>'LKM', 'SEKM'</td>
+ <td>str</td>
+ <td>- Encryption mode of the encryption capable controller.<br>- This option is mandatory when I(rekey) is C(true) and for enabling controller encryption.<br>- C(SEKM) to choose mode as secure enterprise key manager.<br>- C(LKM) to choose mode as local key management.</td>
+ </tr>
+ <tr>
+ <td>attributes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- Dictionary of controller attributes and value pair.<br>- This feature is only supported for iDRAC9 with firmware version 6.00.00.00 and above.<br>- I(controller_id) is required for this operation.<br>- I(apply_time) and I(maintenance_window) is applicable for I(attributes).<br>- Use U(https://I(idrac_ip)/redfish/v1/Schemas/DellOemStorageController.json) to view the attributes.</td>
+ </tr>
+ <tr>
+ <td>apply_time</td>
+ <td>false</td>
+ <td>Immediate</td>
+ <td>'Immediate', 'OnReset', 'AtMaintenanceWindowStart', 'InMaintenanceWindowOnReset'</td>
+ <td>str</td>
+ <td>- Apply time of the I(attributes).<br>- This is applicable only to I(attributes).<br>- C(Immediate) Allows the user to immediately reboot the host and apply the changes. I(job_wait) is applicable.<br>- C(OnReset) Allows the user to apply the changes on the next reboot of the host server.<br>- C(AtMaintenanceWindowStart) Allows the user to apply the changes at the start of a maintenance window as specified in I(maintenance_window).<br>- C(InMaintenanceWindowOnReset) Allows the users to apply after a manual reset but within the maintenance window as specified in I(maintenance_window).</td>
+ </tr>
+ <tr>
+ <td>maintenance_window</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- Option to schedule the maintenance window.<br>- This is required when I(apply_time) is C(AtMaintenanceWindowStart) or C(InMaintenanceWindowOnReset).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start_time</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- The start time for the maintenance window to be scheduled.<br>- The format is YYYY-MM-DDThh:mm:ss<offset>.<br>- <offset> is the time offset from UTC that the current timezone set in iDRAC in the format is +05:30 for IST.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duration</td>
+ <td>false</td>
+ <td>900</td>
+ <td></td>
+ <td>int</td>
+ <td>- The duration in seconds for the maintenance window.</td>
+ </tr>
+</tbody>
+</table>
+
+## Example Playbook
+
+```
+- name: Reset controller configuration
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.0
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ reset_config: true
+```
+
+```
+- name: Set controller attributes
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ attributes:
+ ControllerMode: HBA
+ apply_time: Immediate
+```
+
+```
+- name: Set controller attributes at maintenance window
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ attributes:
+ CheckConsistencyMode: Normal
+ LoadBalanceMode: Disabled
+ apply_time: AtMaintenanceWindowStart
+ maintenance_window:
+ start_time: "2022-09-30T05:15:40-05:00"
+ duration: 1200
+```
+
+```
+- name: Set controller encryption key
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ key: PassPhrase@123
+ key_id: MyKeyId123
+ set_controller_key: true
+```
+
+```
+- name: Rekey in LKM mode
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ rekey: true
+ key: PassPhrase@123
+ key_id: mykeyid123
+ old_key: OldPhassParse@123
+ mode: LKM
+```
+
+```
+- name: Rekey in SEKM mode
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ rekey: true
+ key: PassPhrase@123
+ key_id: mykeyid123
+ old_key: OldPhassParse@123
+ mode: SEKM
+```
+
+```
+- name: Remove controller encryption key
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ remove_key: true
+```
+
+```
+- name: Enable controller encryption
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ set_controller_key: true
+ key: your_key@123
+ key_id: your_keyid@123
+ mode: LKM
+```
+
+```
+- name: Change physical disk state to online
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ status: online
+```
+
+```
+- name: Change physical disk state to offline
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ status: offline
+```
+
+```
+- name: Convert physical disk to RAID mode
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ raid_state: raid
+```
+
+```
+- name: Convert physical disk to Non-RAID mode
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ raid_state: nonraid
+```
+
+```
+- name: Assign dedicated hot spare.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ volumes:
+ id: Disk.Virtual.0:RAID.Slot.1-1
+ dedicated_hot_spare: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+```
+
+```
+- name: Assign global hot spare.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ global_hot_spare: true
+```
+
+```
+- name: Unassign hot spare.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ global_hot_spare: false
+```
+
+```
+- name: Lock virtual drive.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ volumes:
+ id: Disk.Virtual.0:RAID.Slot.1-1
+ encrypted: true
+```
+
+```
+- name: Online capacity expansion of volume using size.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ volumes:
+ id: Disk.Virtual.0:RAID.Slot.1-1
+ expand_capacity_size: 362785
+```
+
+```
+- name: Online capacity expansion of volume using target.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ volumes:
+ id: Disk.Virtual.0:RAID.Slot.1-1
+ expand_capacity_disk: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+```
+
+```
+- name: Blink virtual drive.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ volumes:
+ id: Disk.Virtual.0:RAID.Slot.1-1
+ blink: true
+```
+
+```
+- name: Unblink virtual drive.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ volumes:
+ id: Disk.Virtual.0:RAID.Slot.1-1
+ blink: false
+```
+
+```
+- name: Blink physical disk.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ blink: true
+```
+
+```
+- name: Unblink physical disk.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ ca_path: "/path/to/ca_cert.pem"
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ blink: false
+```
+
+```
+- name: Multiple operations on controller.
+ ansible.builtin.include_role:
+ name: idrac_storage_controller
+ vars:
+ hostname: 192.168.0.1
+ username: username
+ password: password
+ validate_certs: false
+ controller_id: RAID.Slot.1-1
+ disks:
+ id: Disk.Bay.3:Enclosure.Internal.0-1:RAID.Slot.1-1
+ global_hot_spare: false
+ set_controller_key: true
+ key: PassPhrase@12341
+ key_id: mykeyid123
+ mode: LKM
+ attributes:
+ CheckConsistencyMode: StopOnError
+ CopybackMode: OnWithSMART
+ apply_time: Immediate
+```
+
+## Author Information
+------------------
+
+Dell Technologies <br>
+Felix Stephen Anthuvan (felix_s@dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/defaults/main.yml
new file mode 100644
index 000000000..dd4c8e271
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+apply_time: Immediate
+https_port: 443
+https_timeout: 30
+validate_certs: true
+job_wait: true
+job_wait_timeout: 300
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/handlers/main.yml
new file mode 100644
index 000000000..8cec1a4ee
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for idrac_storage_controller
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/argument_specs.yml
new file mode 100644
index 000000000..e26b57242
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/argument_specs.yml
@@ -0,0 +1,200 @@
+---
+argument_specs:
+ main:
+ version_added: "7.6.0"
+ short_description: Configures the physical disk, virtual disk, and storage controller settings
+ description:
+ - This role allows the users to configure the settings of the physical disk, virtual disk,
+ and storage controller on iDRAC9 based PowerEdge servers.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address.
+ username:
+ type: str
+ description: iDRAC username.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ controller_id:
+ required: true
+ description: The ID of the controller on which the operations need to be performed.
+ type: str
+ volumes:
+ type: dict
+ description: List of volume that belongs to I(controller_id).
+ options:
+ id:
+ required: true
+ type: str
+ description: Fully Qualified Device Descriptor (FQDD) of the volume.
+ dedicated_hot_spare:
+ type: str
+ description:
+ - Fully Qualified Device Descriptor (FQDD) of the physical disk to assign the volume
+ as a dedicated hot spare to a disk.
+ encrypted:
+ type: bool
+ description: To encrypt the virtual disk.
+ expand_capacity_disk:
+ type: str
+ description:
+ - Fully Qualified Device Descriptor (FQDD) of the disk for expanding the capacity with
+ the existing disk.
+ - I(expand_capacity_size) is mutually exclusive with I(expand_capacity_disk).
+ expand_capacity_size:
+ type: str
+ description:
+ - Capacity of the virtual disk to be expanded in MB.
+ - Check mode and Idempotency is not supported for I(expand_capacity_size).
+ - Minimum Online Capacity Expansion size must be greater than 100 MB of the current size.
+ - I(expand_capacity_disk) is mutually exclusive with I(expand_capacity_size).
+ blink:
+ type: bool
+ description:
+ - Blinks the target virtual disk and it always reports as changes found when
+ check mode is enabled.
+ disks:
+ type: dict
+ description: List of physical disks that belongs to I(controller_id).
+ options:
+ id:
+ required: true
+ type: str
+ description: Fully Qualified Device Descriptor (FQDD) of the physical disk.
+ blink:
+ type: bool
+ description:
+ - Blinks the target physical disk and it always reports as changes found when
+ check mode is enabled.
+ raid_state:
+ type: str
+ description:
+ - Converts the disk form Non-Raid to Raid and vice versa.
+ - C(raid) converts the physical disk to Raid.
+ - C(nonraid) converts the physical disk to Non Raid.
+ choices: [raid, nonraid]
+ status:
+ type: str
+ description:
+ - Converts the disk form online to offline and vice versa.
+ - C(online) converts the physical disk status to online.
+ - C(offline) converts the physical disk status to offline.
+ choices: [online, offline]
+ global_hot_spare:
+ type: bool
+ description:
+ - Assigns a global hot spare or unassigns a hot spare.
+ - C(true) assigns the disk as a global hot spare.
+ - C(false) unassigns the disk as a hot spare.
+ reset_config:
+ type: bool
+ description: To reset the controller.
+ set_controller_key:
+ type: bool
+ description:
+ - Set the security key or enable controller encryption.
+ - If I(mode) is provided controller encryption operation is performed, otherwise sets the
+ controller security key.
+ - I(key), and I(key_id) are required for this operation.
+ rekey:
+ type: bool
+ description: Resets the key on the controller and it always reports as changes found when check mode is enabled.
+ remove_key:
+ type: bool
+ description: Remove the key on controllers.
+ key:
+ type: str
+ description:
+ - A new security key passphrase that the encryption-capable controller uses to create the
+ encryption key. The controller uses the encryption key to lock or unlock access to the Self-Encrypting
+ Drive (SED). Only one encryption key can be created for each controller.
+ - This is mandatory when I(set_controller_key) is C(true), I(rekey) is C(true).
+ - The length of the key can be a maximum of 32 characters in length, where the expanded form of the special
+ character is counted as a single character.
+ - The key must contain at least one character from each of the character classes are uppercase, lowercase,
+ number, and special character.
+ key_id:
+ type: str
+ description:
+ - This is a user supplied text label associated with the passphrase.
+ - This is mandatory when I(set_controller_key) is C(true), I(rekey) is C(true).
+ - The length of I(key_id) can be a maximum of 32 characters in length and should not have any spaces.
+ old_key:
+ type: str
+ description:
+ - Security key passphrase used by the encryption-capable controller.
+ - This option is mandatory when I(rekey) is C(true).
+ mode:
+ type: str
+ description:
+ - Encryption mode of the encryption capable controller.
+ - This option is mandatory when I(rekey) is C(true) and for enabling controller encryption.
+ - C(SEKM) to choose mode as secure enterprise key manager.
+ - C(LKM) to choose mode as local key management.
+ choices: [LKM, SEKM]
+ attributes:
+ type: dict
+ description:
+ - Dictionary of controller attributes and value pair.
+ - This feature is only supported for iDRAC9 with firmware version 6.00.00.00 and above.
+ - I(controller_id) is required for this operation.
+ - I(apply_time) and I(maintenance_window) is applicable for I(attributes).
+ - Use U(https://I(idrac_ip)/redfish/v1/Schemas/DellOemStorageController.json) to view the attributes.
+ apply_time:
+ type: str
+ description:
+ - Apply time of the I(attributes).
+ - This is applicable only to I(attributes).
+ - C(Immediate) Allows the user to immediately reboot the host and apply the changes. I(job_wait)
+ is applicable.
+ - C(OnReset) Allows the user to apply the changes on the next reboot of the host server.
+ - C(AtMaintenanceWindowStart) Allows the user to apply the changes at the start of a maintenance window
+ as specified in I(maintenance_window).
+ - C(InMaintenanceWindowOnReset) Allows the users to apply after a manual reset but within the maintenance
+ window as specified in I(maintenance_window).
+ choices:
+ [
+ Immediate,
+ OnReset,
+ AtMaintenanceWindowStart,
+ InMaintenanceWindowOnReset,
+ ]
+ default: Immediate
+ maintenance_window:
+ type: dict
+ description:
+ - Option to schedule the maintenance window.
+ - This is required when I(apply_time) is C(AtMaintenanceWindowStart) or C(InMaintenanceWindowOnReset).
+ options:
+ start_time:
+ required: true
+ type: str
+ description:
+ - The start time for the maintenance window to be scheduled.
+ - The format is YYYY-MM-DDThh:mm:ss<offset>
+ - <offset> is the time offset from UTC that the current timezone set in iDRAC in the
+ format is +05:30 for IST.
+ duration:
+ type: int
+ description: The duration in seconds for the maintenance window.
+ default: 900
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/main.yml
new file mode 100644
index 000000000..40024380a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/meta/main.yml
@@ -0,0 +1,26 @@
+galaxy_info:
+ role_name: idrac_storage_controller
+ author: Felix Stephen
+ description: The role performs the iDRAC storage controller operations.
+ company: Dell Technologies
+
+ license: GPL-3.0-only
+
+ min_ansible_version: "2.13"
+
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tasks/main.yml
new file mode 100644
index 000000000..0c23a324c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tasks/main.yml
@@ -0,0 +1,200 @@
+---
+- name: Setting up hostname with port
+ ansible.builtin.set_fact:
+ baseuri: "{{ hostname }}:{{ https_port }}"
+
+- name: Setting common options
+ ansible.builtin.set_fact:
+ idrac_inputs: &idrac_inputs
+ baseuri: "{{ baseuri }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ timeout: "{{ https_timeout }}"
+ no_log: true
+
+- name: Storage controller reset configuration.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "ResetConfig"
+ controller_id: "{{ controller_id }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: reset_config_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: reset_config is true
+
+- name: Storage controller attributes configuration.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ controller_id: "{{ controller_id }}"
+ attributes: "{{ attributes }}"
+ apply_time: "{{ apply_time }}"
+ maintenance_window: "{{ maintenance_window | default(omit) }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: attributes_config_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: attributes is defined
+
+- name: Storage set controller key configuration.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "SetControllerKey"
+ controller_id: "{{ controller_id }}"
+ key: "{{ key | default(omit) }}"
+ key_id: "{{ key_id | default(omit) }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: set_controller_key_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: set_controller_key is true and key is defined and key_id is defined and mode is undefined
+
+- name: Storage remove controller key configuration.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "RemoveControllerKey"
+ controller_id: "{{ controller_id }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: remove_controller_key_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: remove_key is true
+
+- name: Storage controller rekey configuration.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "ReKey"
+ controller_id: "{{ controller_id }}"
+ key: "{{ key | default(omit) }}"
+ key_id: "{{ key_id | default(omit) }}"
+ old_key: "{{ old_key | default(omit) }}"
+ mode: "{{ mode | default(omit) }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: storage_controller_rekey
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: rekey is true
+
+- name: Storage enable controller encryption.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "EnableControllerEncryption"
+ controller_id: "{{ controller_id }}"
+ key: "{{ key | default(omit) }}"
+ key_id: "{{ key_id | default(omit) }}"
+ mode: "{{ mode | default(omit) }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: enable_encryption_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when:
+ set_controller_key is true and key is defined and key_id is defined and mode is defined
+
+- name: Change physical disk state.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "{{ 'ChangePDStateToOnline' if disks.status == 'online' else 'ChangePDStateToOffline' }}"
+ controller_id: "{{ controller_id }}"
+ target: "{{ disks.id }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: pd_state_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: disks.status is defined
+
+- name: Change physical disk raid state.
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "{{ 'ConvertToRAID' if disks.raid_state == 'raid' else 'ConvertToNonRAID' }}"
+ controller_id: "{{ controller_id }}"
+ target: "{{ disks.id }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: raid_state_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: disks.raid_state is defined
+
+- name: Assign dedicated hot spare
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "AssignSpare"
+ controller_id: "{{ controller_id }}"
+ volume_id: "{{ volumes.id }}"
+ target: "{{ volumes.dedicated_hot_spare }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: assign_dedicated_spare_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: volumes.id is defined and volumes.dedicated_hot_spare is defined
+
+- name: Assign global hot spare
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "AssignSpare"
+ controller_id: "{{ controller_id }}"
+ target: "{{ disks.id }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: assign_global_spare_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: disks.id is defined and disks.global_hot_spare is true
+
+- name: Unassign hot spare
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "UnassignSpare"
+ controller_id: "{{ controller_id }}"
+ target: "{{ disks.id }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: unassign_hotspare_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: disks.global_hot_spare is false and disks.id is defined
+
+- name: Lock virtual disk
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "LockVirtualDisk"
+ controller_id: "{{ controller_id }}"
+ volume_id: "{{ volumes.id }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: lock_vd_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: volumes.encrypted is true
+
+- name: Online capacity expansion of a volume using target
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "OnlineCapacityExpansion"
+ controller_id: "{{ controller_id }}"
+ volume_id: "{{ volumes.id }}"
+ target: "{{ volumes.expand_capacity_disk | default(omit) }}"
+ size: "{{ volumes.expand_capacity_size | default(omit) }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: oce_vd_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: volumes.expand_capacity_disk is defined or volumes.expand_capacity_size is defined
+
+- name: Blink and Un-blink virtual disk
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "{{ 'BlinkTarget' if volumes.blink is true else 'UnBlinkTarget' }}"
+ controller_id: "{{ controller_id }}"
+ volume_id: "{{ volumes.id }}"
+ register: blink_vd_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: volumes.blink is defined
+
+- name: Blink and Un-blink physical disk
+ dellemc.openmanage.idrac_redfish_storage_controller:
+ <<: *idrac_inputs
+ command: "{{ 'BlinkTarget' if disks.blink is true else 'UnBlinkTarget' }}"
+ controller_id: "{{ controller_id }}"
+ target: "{{ disks.id }}"
+ register: blink_pd_out
+ delegate_to: "{{ idrac_storage_controller_task_delegate }}"
+ when: disks.blink is defined
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/inventory b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/test.yml
new file mode 100644
index 000000000..7e20bbe3c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Executing iDRAC storage controller role
+ hosts: localhost
+ remote_user: root
+ roles:
+ - idrac_storage_controller
diff --git a/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/vars/main.yml
new file mode 100644
index 000000000..7bb065621
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/idrac_storage_controller/vars/main.yml
@@ -0,0 +1,2 @@
+---
+idrac_storage_controller_task_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/molecule.yml b/ansible_collections/dellemc/openmanage/roles/molecule.yml
new file mode 100644
index 000000000..231e04e0b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/molecule.yml
@@ -0,0 +1,37 @@
+---
+dependency:
+ name: galaxy
+ enabled: false
+driver:
+ name: podman
+platforms:
+ - name: centos
+ image: quay.io/centos/centos:stream8
+ pre_build_image: true
+ volumes:
+ - /tmp:/tmp
+provisioner:
+ name: ansible
+ env:
+ idrac_powercycle_wait_seconds: 180
+ idrac_certificate_delegate_to: localhost
+ redfish_firmware_image_url_need_reboot: "https://dl.dell.com/FOLDER07217671M/1/SAS-RAID_Firmware_700GG_WN64_25.5.9.0001_A17.EXE"
+ redfish_firmware_image_url_without_reboot: "https://dl.dell.com/FOLDER10335817M/1/Diagnostics_Application_31T12_WN64_4303A02_4303.2.EXE"
+ redfish_firmware_image_local_path: "/tmp/redfish_firmware"
+verifier:
+ name: ansible
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - prepare
+ - check
+ - converge
+ - idempotence
+ - side_effect
+ - verify
+ - cleanup
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/README.md b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/README.md
new file mode 100644
index 000000000..69f9989cf
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/README.md
@@ -0,0 +1,219 @@
+# redfish_firmware
+
+To perform a component firmware update using the image file available on the local or remote system.
+
+## Requirements
+
+---
+
+
+### Development
+Requirements to develop and contribute to the role.
+
+```
+ansible
+docker
+molecule
+python
+```
+
+### Production
+
+Requirements to use the role.
+
+```
+ansible
+python
+```
+
+## Ansible collections
+
+Collections required to use the role.
+
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+---
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>image_uri</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Firmware Image location URI or local path.
+ <br>- For example- U(http://<web_address>/components.exe) or /home/firmware_repo/component.exe.
+ </td>
+ </tr>
+ <tr>
+ <td>transfer_protocol</td>
+ <td>false</td>
+ <td>HTTP</td>
+ <td>"CIFS", "FTP", "HTTP", "HTTPS", "NSF", "OEM", "SCP", "SFTP", "TFTP"</td>
+ <td>str</td>
+ <td>- Protocol used to transfer the firmware image file. Applicable for URI based update.</td>
+ </tr>
+ <tr>
+ <td>job_wait</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>str</td>
+ <td>- Provides the option to wait for job completion.</td>
+ </tr>
+ <tr>
+ <td>job_wait_timeout</td>
+ <td>false</td>
+ <td>3600</td>
+ <td></td>
+ <td>str</td>
+ <td>- The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.
+ <br>- This option is applicable when I(job_wait) is C(True).
+ </td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>redfish_firmware_out</td>
+ <td>{
+ msg: Successfully submitted the firmware update task.
+ task: {
+ "id": "JID_XXXXXXXXXXXX",
+ "uri": "/redfish/v1/TaskService/Tasks/JID_XXXXXXXXXXXX"
+ }
+ }</td>
+ <td>Returns the output of the firmware update status.</td>
+ </tr>
+ </tbody>
+</table>
+
+## Examples
+
+---
+
+```
+- name: Update the firmware from a single executable file available in HTTP protocol
+ ansible.builtin.include_role:
+ name: redfish_firmware:
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ image_uri: "http://192.168.0.2/firmware_repo/component.exe"
+ transfer_protocol: "HTTP"
+```
+
+```
+- name: Update the firmware from a single executable file available in a local path
+ ansible.builtin.include_role:
+ name: redfish_firmware:
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ image_uri: "/home/firmware_repo/component.exe"
+```
+
+```
+- name: Update the firmware from a single executable file available in a HTTP protocol with job_wait_timeout
+ ansible.builtin.include_role:
+ name: redfish_firmware:
+ vars:
+ hostname: "192.168.0.1"
+ username: "user_name"
+ password: "user_password"
+ ca_path: "/path/to/ca_cert.pem"
+ image_uri: "http://192.168.0.2/firmware_repo/component.exe"
+ transfer_protocol: "HTTP"
+ job_wait_timeout: 600
+```
+
+## Author Information
+
+---
+
+Dell Technologies <br>
+Shivam Sharma (Shivam.Sharma3@Dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/defaults/main.yml
new file mode 100644
index 000000000..6a1d8fe6e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+# defaults file for redfish_firmware
+
+https_port: 443
+validate_certs: true
+https_timeout: 30
+job_wait_timeout: 3600
+transfer_protocol: HTTP
+job_wait: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/handlers/main.yml
new file mode 100644
index 000000000..6c0214362
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for redfish_firmware
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/argument_specs.yml
new file mode 100644
index 000000000..1396b9bd8
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/argument_specs.yml
@@ -0,0 +1,60 @@
+---
+argument_specs:
+ main:
+ version_added: "7.5.0"
+ short_description: Update a component firmware using the image file available on the local or remote system
+ description:
+ - This module allows the firmware update of only one component at a time. If the module is run for more than one component, an error message is returned.
+ - Depending on the component, the firmware update is applied after an automatic or manual reboot.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address or hostname.
+ username:
+ type: str
+ description: iDRAC username with admin privileges.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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.
+ - Prior to collection version 5.0.0, I(validate_certs) is C(False) by default.
+ type: bool
+ default: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ http_timeout:
+ description: The socket level timeout in seconds.
+ type: int
+ default: 30
+ image_uri:
+ description:
+ - Firmware Image location URI or local path.
+ - For example- U(http://<web_address>/components.exe) or /home/firmware_repo/component.exe.
+ type: str
+ required: true
+ transfer_protocol:
+ description: Protocol used to transfer the firmware image file. Applicable for URI based update.
+ type: str
+ default: HTTP
+ choices:
+ ["CIFS", "FTP", "HTTP", "HTTPS", "NSF", "OEM", "SCP", "SFTP", "TFTP"]
+ job_wait:
+ description: Provides the option to wait for job completion.
+ type: bool
+ default: true
+ job_wait_timeout:
+ description:
+ - The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.
+ - This option is applicable when I(job_wait) is C(True).
+ type: int
+ default: 3600
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/main.yml
new file mode 100644
index 000000000..f9b757aff
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/meta/main.yml
@@ -0,0 +1,55 @@
+galaxy_info:
+ author: "Shivam Sharma"
+ description: To perform a component firmware update using the image file available on the local or remote system.
+ company: Dell Technologies
+
+ # 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.13"
+
+ # If this a Container Enabled role, provide the minimum Ansible Container version.
+ # min_ansible_container_version:
+
+ #
+ # Provide a list of supported platforms, and for each platform a list of versions.
+ # If you don't wish to enumerate all versions for a particular platform, use 'all'.
+ # To view available platforms and versions (or releases), visit:
+ # https://galaxy.ansible.com/api/v1/platforms/
+ #
+ platforms:
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+
+ 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.
+
+dependencies:
+ []
+ # List your role dependencies here, one per line. Be sure to remove the '[]' above,
+ # if you add dependencies to this list.
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/converge.yml
new file mode 100644
index 000000000..26d2c476c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/converge.yml
@@ -0,0 +1,74 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ redfish_firmware_image_url_without_reboot: "{{ lookup('env', 'redfish_firmware_image_url_without_reboot') }}"
+ redfish_firmware_image_url_need_reboot: "{{ lookup('env', 'redfish_firmware_image_url_need_reboot') }}"
+ redfish_firmware_image_local_path: "{{ lookup('env', 'redfish_firmware_image_local_path') }}"
+ gather_facts: false
+ tasks:
+ - name: Checking if HTTP url is empty
+ ansible.builtin.fail:
+ msg: Please provide HTTP url for redfish_firmware in molecule.yml
+ when: redfish_firmware_image_url_without_reboot == "" and redfish_firmware_image_url_need_reboot == ""
+
+ - name: Downloading firmware image for local manual reboot
+ ansible.builtin.get_url:
+ url: "{{ redfish_firmware_image_url_need_reboot }}"
+ dest: "{{ redfish_firmware_image_local_path }}"
+ mode: "0755"
+ delegate_to: localhost
+
+ - name: Initializing idrac common inputs to use as aliases
+ ansible.builtin.set_fact:
+ common_input: &idrac_input
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ no_log: true
+
+ - name: TC - 001 - Provide valid HTTP image_uri with default transfer_protocol with auto reboot
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ <<: *idrac_input
+ image_uri: "{{ redfish_firmware_image_url_without_reboot }}"
+ job_wait_timeout: 3600
+
+ - name: TC - 001 - Asserting after performing update with valid image_uri and default transfter_protocol with auto reboot
+ ansible.builtin.assert:
+ that:
+ - redfish_firmware_out.msg == 'Successfully updated the firmware.'
+ - redfish_firmware_out.changed
+
+ - name: TC - 002 - Provide valid local image_uri firmware to schedule job with job_wait_timeout 60 secs
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ <<: *idrac_input
+ image_uri: "{{ redfish_firmware_image_url_need_reboot }}"
+ job_wait_timeout: 60
+
+ - name: TC - 002 - Asserting after performing update with local image_uri firmware to schedule job
+ ansible.builtin.assert:
+ that:
+ - redfish_firmware_out.msg == "Successfully scheduled the firmware job."
+ - redfish_firmware_out.changed
+
+ - name: TC - 002 - Deleting the schedule job in iDRAC
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}/redfish/v1/JobService/Jobs/{{ redfish_firmware_out.task.id }}"
+ validate_certs: false
+ method: "DELETE"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ status_code:
+ - 200
+ return_content: true
+ no_log: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/molecule.yml
new file mode 100644
index 000000000..484f43c65
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/default/molecule.yml
@@ -0,0 +1,15 @@
+---
+provisioner:
+ name: ansible
+ playbooks:
+ prepare: ../resources/prepare.yml
+ cleanup: ../resources/cleanup.yml
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/converge.yml
new file mode 100644
index 000000000..86196dc82
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/converge.yml
@@ -0,0 +1,174 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+ vars:
+ redfish_firmware_image_url_without_reboot: "{{ lookup('env', 'redfish_firmware_image_url_without_reboot') }}"
+ redfish_firmware_image_url_need_reboot: "{{ lookup('env', 'redfish_firmware_image_url_need_reboot') }}"
+ redfish_firmware_image_local_path: "{{ lookup('env', 'redfish_firmware_image_local_path') }}"
+ tasks:
+ - name: Checking if HTTP url is empty
+ ansible.builtin.fail:
+ msg: Please provide HTTP url for redfish_firmware in molecule.yml
+ when: redfish_firmware_image_url_without_reboot == "" and redfish_firmware_image_url_need_reboot == ""
+
+ - name: Downloading firmware image for local manual reboot
+ ansible.builtin.get_url:
+ url: "{{ redfish_firmware_image_url_need_reboot }}"
+ dest: "{{ redfish_firmware_image_local_path }}"
+ mode: "0755"
+ delegate_to: localhost
+
+ - name: TC - 003 - Provide wrong hostname
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ hostname: "randomHostname"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ image_uri: "{{ redfish_firmware_image_url_need_reboot }}"
+ job_wait_timeout: 60
+ ignore_errors: true
+ ignore_unreachable: true
+ register: redfish_firmware_error_msg
+
+ - name: TC - 003 - Asserting wrong hostname
+ ansible.builtin.assert:
+ that:
+ - redfish_firmware_out.msg == "<urlopen error [Errno -2] Name or service not known>" or
+ redfish_firmware_out.msg == "<urlopen error Unable to resolve hostname or IP randomHostname:443.>"
+
+ - name: TC - 004 - Provide wrong username
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "WrongUsername123"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ image_uri: "{{ redfish_firmware_image_url_need_reboot }}"
+ job_wait_timeout: 60
+ ignore_errors: true
+ ignore_unreachable: true
+ register: redfish_firmware_error_msg
+
+ - name: TC - 004 - Asserting wrong username
+ ansible.builtin.assert:
+ that:
+ - '"HTTP Error 401" in redfish_firmware_out.msg'
+
+ - name: TC - 005 - Provide wrong password
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "WrongPassword@123"
+ validate_certs: false
+ image_uri: "{{ redfish_firmware_image_url_need_reboot }}"
+ job_wait_timeout: 60
+ ignore_errors: true
+ ignore_unreachable: true
+ register: redfish_firmware_error_msg
+
+ - name: TC - 005 - Asserting wrong password
+ ansible.builtin.assert:
+ that: |-
+ ('"HTTP Error 401" in redfish_firmware_out.msg')
+ or
+ ('"urlopen error timed out" in redfish_firmware_out.msg')
+
+ - name: TC - 006 - Providing invalid validate_certs
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: 'someStringValue'
+ image_uri: "{{ redfish_firmware_image_url_need_reboot }}"
+ job_wait_timeout: 60
+ ignore_errors: true
+ ignore_unreachable: true
+ register: redfish_firmware_error_msg
+
+ - name: TC - 006 - Asserting invalid validate_certs
+ ansible.builtin.assert:
+ that:
+ - '"Valid booleans include" in redfish_firmware_out.msg'
+
+ - name: TC - 007 - Providing invalid local path in image_uri
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ image_uri: "/tmp/file_not_exists.iso"
+ job_wait_timeout: 60
+ ignore_errors: true
+ register: redfish_firmware_error_msg
+
+ - name: TC - 007 - Asserting invalid local path in image_uri
+ ansible.builtin.assert:
+ that:
+ - '"No such file or directory" in redfish_firmware_out.msg'
+
+ - name: TC - 008 - Providing invalid HTTP in image_uri
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ image_uri: "http://www.example.com"
+ job_wait_timeout: 60
+ ignore_errors: true
+ register: redfish_firmware_error_msg
+
+ - name: TC - 008 - Asserting invalid HTTP in image_uri
+ ansible.builtin.assert:
+ that:
+ - redfish_firmware_out.msg == "Firmware update failed."
+ - not redfish_firmware_out.changed
+
+ - name: TC - 009 - Providing job_wait_timeout as -100 with auto reboot firmware component
+ ansible.builtin.import_role:
+ name: redfish_firmware
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ image_uri: "{{ redfish_firmware_image_url_without_reboot }}"
+ job_wait_timeout: -100
+
+ - name: TC - 009 - Asserting job_wait_timeout as -100 with auto reboot firmware component
+ ansible.builtin.assert:
+ that:
+ - redfish_firmware_out.msg == "Successfully submitted the firmware update task."
+ - redfish_firmware_out.changed
+
+ - name: TC - 009 - Waiting for job completion
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}/redfish/v1/JobService/Jobs/{{ redfish_firmware_out.task.id }}"
+ validate_certs: false
+ method: "GET"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ headers:
+ Accept: "application/json"
+ Content-Type: "application/json"
+ OData-Version: "4.0"
+ body_format: "json"
+ status_code:
+ - 200
+ return_content: true
+ register: job_result
+ until: job_result.json.JobState == 'Completed' or job_result.json.JobState == 'Failed'
+ retries: 30
+ delay: 10
+ when: redfish_firmware_out.changed # noqa: no-handler
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/molecule.yml
new file mode 100644
index 000000000..484f43c65
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/negative/molecule.yml
@@ -0,0 +1,15 @@
+---
+provisioner:
+ name: ansible
+ playbooks:
+ prepare: ../resources/prepare.yml
+ cleanup: ../resources/cleanup.yml
+scenario:
+ test_sequence:
+ - dependency
+ - cleanup
+ - destroy
+ - syntax
+ - create
+ - converge
+ - destroy
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/cleanup.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/cleanup.yml
new file mode 100644
index 000000000..bfffc48fd
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/cleanup.yml
@@ -0,0 +1,16 @@
+- name: Cleanup
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Check if directory exists
+ ansible.builtin.stat:
+ path: "{{ lookup('env', 'redfish_firmware_image_local_path') }}"
+ register: directory_check
+ delegate_to: localhost
+
+ - name: Delete directory if it exists
+ ansible.builtin.file:
+ path: "{{ lookup('env', 'redfish_firmware_image_local_path') }}"
+ state: absent
+ when: directory_check.stat.exists
+ delegate_to: localhost
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/prepare.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/prepare.yml
new file mode 100644
index 000000000..17c1a617a
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/molecule/resources/prepare.yml
@@ -0,0 +1,17 @@
+- name: Prepare
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Checking if path exists
+ ansible.builtin.stat:
+ path: "{{ lookup('env', 'redfish_firmware_image_local_path') }}"
+ register: directory_check
+ delegate_to: localhost
+
+ - name: Create directory if it doesn't exist
+ ansible.builtin.file:
+ path: "{{ lookup('env', 'redfish_firmware_image_local_path') }}"
+ state: directory
+ mode: "0755"
+ when: directory_check.stat.exists
+ delegate_to: localhost
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tasks/main.yml
new file mode 100644
index 000000000..418e8a7ac
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+# tasks file for redfish_firmware
+- name: Update the firmware from a single executable file.
+ dellemc.openmanage.redfish_firmware:
+ baseuri: "{{ hostname }}:{{ https_port }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ timeout: "{{ https_timeout }}"
+ image_uri: "{{ image_uri }}"
+ transfer_protocol: "{{ transfer_protocol }}"
+ job_wait: "{{ job_wait }}"
+ job_wait_timeout: "{{ job_wait_timeout }}"
+ register: redfish_firmware_out
+ delegate_to: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/inventory b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/test.yml
new file mode 100644
index 000000000..8a43f29b7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/tests/test.yml
@@ -0,0 +1,5 @@
+---
+- name: Upgrading Firmware
+ hosts: all
+ roles:
+ - redfish_firmware
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_firmware/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/vars/main.yml
new file mode 100644
index 000000000..849f79286
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_firmware/vars/main.yml
@@ -0,0 +1,2 @@
+---
+# vars file for redfish_firmware
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/README.md b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/README.md
new file mode 100644
index 000000000..fa023fb22
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/README.md
@@ -0,0 +1,417 @@
+# redfish_storage_volume
+
+Role to create, modify, initialize, or delete a single storage volume.
+
+## Requirements
+
+### Development
+
+Requirements to develop and contribute to the role.
+
+```
+ansible
+docker
+molecule
+python
+```
+
+### Production
+
+Requirements to use the role.
+
+```
+ansible
+python
+```
+
+### Ansible collections
+
+Collections required to use the role
+
+```
+dellemc.openmanage
+```
+
+## Role Variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Required</th>
+ <th>Default Value</th>
+ <th>Choices</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>hostname</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC IP Address</td>
+ </tr>
+ <tr>
+ <td>username</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC username</td>
+ </tr>
+ <tr>
+ <td>password</td>
+ <td>true</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- iDRAC user password.</td>
+ </tr>
+ <tr>
+ <td>https_port</td>
+ <td>false</td>
+ <td>443</td>
+ <td></td>
+ <td>int</td>
+ <td>- iDRAC port.</td>
+ </tr>
+ <tr>
+ <td>validate_certs</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</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>
+ </tr>
+ <tr>
+ <td>ca_path</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>path</td>
+ <td>- The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.</td>
+ </tr>
+ <tr>
+ <td>https_timeout</td>
+ <td>false</td>
+ <td>30</td>
+ <td></td>
+ <td>int</td>
+ <td>- The HTTPS socket level timeout in seconds.</td>
+ </tr>
+ <tr>
+ <td>controller_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Fully Qualified Device Descriptor (FQDD) of the storage controller.For example- RAID.Slot.1-1.</br>This option is mandatory when I(state) is C(present) while creating a volume.</td>
+ </tr>
+ <tr>
+ <td>volume_id</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- FQDD of existing volume.For example- Disk.Virtual.4:RAID.Slot.1-1. </br>- This option is mandatory in the following scenarios, I(state) is C(present), when updating a volume. I(state) is C(absent), when deleting a volume.I(command) is C(initialize), when initializing a volume.</td>
+ </tr>
+ <tr>
+ <td>state</td>
+ <td>false</td>
+ <td>present</td>
+ <td>[present, absent]</td>
+ <td>str</td>
+ <td>- C(present) creates a storage volume for the specified I (controller_id), or modifies the storage volume for the specified I (volume_id). "Note: Modification of an existing volume properties depends on drive and controller capabilities". </br> C(absent) deletes the volume for the specified I(volume_id).</td>
+ </tr>
+ <tr>
+ <td>command</td>
+ <td>false</td>
+ <td></td>
+ <td>[initialize]</td>
+ <td>str</td>
+ <td>- C(initialize) initializes an existing storage volume for a specified I(volume_id).</td>
+ </tr>
+ <tr>
+ <td>raid_type</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- One of the following raid types must be selected to create a volume.</br>
+ - C(RAID0) to create a RAID0 type volume.</br>
+ - C(RAID1) to create a RAID1 type volume.</br>
+ - C(RAID5) to create a RAID5 type volume.</br>
+ - C(RAID6) to create a RAID6 type volume.</br>
+ - C(RAID10) to create a RAID10 type volume.</br>
+ - C(RAID50) to create a RAID50 type volume.</br>
+ - C(RAID60) to create a RAID60 type volume.</td>
+ </tr>
+ <tr>
+ <td>name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Name of the volume to be created.</br>
+- Only applicable when I(state) is C(present).</br>
+- This will be deprecated. Please use I(volume_name) for specifying the volume name.</td>
+ </tr>
+ <tr>
+ <td>volume_name</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Name of the volume to be created.</br>
+- Only applicable when I(state) is C(present).</td>
+ </tr>
+ <tr>
+ <td>drives</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>list</td>
+ <td>- FQDD of the Physical disks. For example- Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1. </br>- Only applicable when I(state) is C(present) when creating a new volume.</td>
+ </tr>
+ <tr>
+ <td>block_size_bytes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>int</td>
+ <td>- Block size in bytes.Only applicable when I(state) is C(present).</td>
+ </tr>
+ </tr>
+ <tr>
+ <td>capacity_bytes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Volume size in bytes.</br>- Only applicable when I(state) is C(present).</td>
+ </tr>
+ <tr>
+ <td>optimum_io_size_bytes</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>str</td>
+ <td>- Stripe size value must be in multiples of 64 * 1024.</br>- Only applicable when I(state) is C(present).</td>
+ </tr>
+ <tr>
+ <td>encryption_types</td>
+ <td>false</td>
+ <td></td>
+ <td>[NativeDriveEncryption, ControllerAssisted, SoftwareAssisted]</td>
+ <td>str</td>
+ <td>- The following encryption types can be selected.</br>
+C(ControllerAssisted) The volume is encrypted by the storage controller entity.</br>
+C(NativeDriveEncryption) The volume utilizes the native drive encryption capabilities of the drive hardware.</br>
+C(SoftwareAssisted) The volume is encrypted by the software running on the system or the operating system.</br>
+Only applicable when I(state) is C(present).</td>
+ </tr>
+ <tr>
+ <td>encrypted</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>bool</td>
+ <td>- Indicates whether volume is currently utilizing encryption or not.</br>- Only applicable when I(state) is C(present).</td>
+ </tr>
+ <tr>
+ <td>oem</td>
+ <td>false</td>
+ <td></td>
+ <td></td>
+ <td>dict</td>
+ <td>- Includes OEM extended payloads.</br>- Only applicable when I(state) is I(present).</td>
+ </tr>
+ <tr>
+ <td>initialize_type</td>
+ <td>false</td>
+ <td>Fast</td>
+ <td>[Fast, Slow]</td>
+ <td>str</td>
+ <td>- Initialization type of existing volume.</br> Only applicable when I(command) is C(initialize).</td>
+ </tr>
+ <tr>
+ <td>job_wait</td>
+ <td>false</td>
+ <td>true</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Determines whether to wait for the job completion or not.</td>
+ </tr>
+ <tr>
+ <td>job_wait_timeout</td>
+ <td>false</td>
+ <td></td>
+ <td>300</td>
+ <td>int</td>
+ <td>- The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.</br>- This option is applicable when I(job_wait) is C(True).</td>
+ </tr>
+ <tr>
+ <td>apply_time</td>
+ <td>false</td>
+ <td></td>
+ <td>[Immediate, OnReset]</td>
+ <td>str</td>
+ <td>- Apply time of the Volume configuration.</br>
+- C(Immediate) allows you to apply the volume configuration on the host server immediately and apply the changes. This is applicable for I(job_wait).</br>
+- C(OnReset) allows you to apply the changes on the next reboot of the host server.</br>
+- I(apply_time) has a default value based on the different types of the controller.</br>
+- For example, BOSS-S1 and BOSS-N1 controllers have a default value of I(apply_time) as C(OnReset).</br>
+- PERC controllers have a default value of I(apply_time) as C(Immediate).</td>
+ </tr>
+ <tr>
+ <td>reboot_server</td>
+ <td></td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Reboot the server to apply the changes.</br>
+- I(reboot_server) is applicable only when I(apply_timeout) is C(OnReset) or when the default value for the apply time of the controller is C(OnReset).</td>
+ </tr>
+ <tr>
+ <td>force_reboot</td>
+ <td></td>
+ <td>false</td>
+ <td></td>
+ <td>bool</td>
+ <td>- Reboot the server forcefully to apply the changes when the normal reboot fails.</br>
+- I(force_reboot) is applicable only when I(reboot_server) is C(true).</td>
+ </tr>
+</tbody>
+</table>
+
+## Fact variables
+
+<table>
+<thead>
+ <tr>
+ <th>Name</th>
+ <th>Sample</th>
+ <th>Description</th>
+ </tr>
+</thead>
+ <tbody>
+ <tr>
+ <td>redfish_storage_volume_out</td>
+ <td>{"changed": true,
+ "failed": false,
+ "msg": "Successfully submitted create volume task."
+}</td>
+<td>Module output of the redfish storage volume</td>
+</tbody>
+</table>
+
+## Examples
+
+---
+
+```yml
+- name: Create a volume with supported options
+ ansible.builtin.include_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ state: "present"
+ raid_type: "RAID1"
+ volume_name: "VD0"
+ controller_id: "RAID.Slot.1-1"
+ drives:
+ - Disk.Bay.5:Enclosure.Internal.0-1:RAID.Slot.1-1
+ - Disk.Bay.6:Enclosure.Internal.0-1:RAID.Slot.1-1
+ block_size_bytes: 512
+ capacity_bytes: 299439751168
+ optimum_io_size_bytes: 65536
+ encryption_types: NativeDriveEncryption
+ encrypted: true
+```
+
+```yml
+- name: Create a volume with apply time
+ ansible.builtin.include_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ state: "present"
+ raid_type: "RAID6"
+ volume_name: "Raid6_VD"
+ controller_id: "RAID.Slot.1-1"
+ drives:
+ - Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1
+ - Disk.Bay.2:Enclosure.Internal.0-1:RAID.Slot.1-1
+ - Disk.Bay.5:Enclosure.Internal.0-1:RAID.Slot.1-1
+ - Disk.Bay.6:Enclosure.Internal.0-1:RAID.Slot.1-1
+ apply_time: OnReset
+ reboot_server: true
+ force_reboot: true
+```
+
+```yml
+- name: Create a volume with minimum options
+ ansible.builtin.include_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ state: "present"
+ controller_id: "RAID.Slot.1-1"
+ raid_type: "RAID0"
+ drives:
+ - Disk.Bay.1:Enclosure.Internal.0-1:RAID.Slot.1-1
+```
+
+```yml
+- name: Modify a volume's encryption type settings
+ ansible.builtin.include_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ state: "present"
+ volume_id: "Disk.Virtual.5:RAID.Slot.1-1"
+ encryption_types: "ControllerAssisted"
+ encrypted: true
+```
+
+```yml
+- name: Delete an existing volume
+ ansible.builtin.include_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ state: "absent"
+ volume_id: "Disk.Virtual.5:RAID.Slot.1-1"
+```
+
+```yml
+- name: Initialize an existing volume
+ ansible.builtin.include_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "192.168.0.1"
+ username: "username"
+ password: "password"
+ command: "initialize"
+ volume_id: "Disk.Virtual.6:RAID.Slot.1-1"
+ initialize_type: "Slow"
+```
+## Author Information
+
+---
+
+Dell Technologies <br>
+Kritika Bhateja (Kritika.Bhateja@Dell.com) 2023
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/defaults/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/defaults/main.yml
new file mode 100644
index 000000000..3c7eeccfe
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/defaults/main.yml
@@ -0,0 +1,10 @@
+---
+# defaults file for idrac_server_powerstate
+validate_certs: true
+https_timeout: 30
+https_port: 443
+initialize_type: "Fast"
+job_wait: true
+job_wait_timeout: 1200
+reboot_server: false
+force_reboot: false
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/handlers/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/handlers/main.yml
new file mode 100644
index 000000000..adce9c861
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for redfish_storage_volume
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/argument_specs.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/argument_specs.yml
new file mode 100644
index 000000000..fdaf8ea52
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/argument_specs.yml
@@ -0,0 +1,176 @@
+---
+argument_specs:
+ main:
+ version_added: "7.5.0"
+ short_description: Role to manage the storage volume configuration
+ description:
+ - Role to create, modify, initialize, or delete a single storage volume.
+ options:
+ hostname:
+ required: true
+ type: str
+ description: iDRAC IP Address or hostname.
+ username:
+ type: str
+ description: iDRAC username with admin privilages.
+ password:
+ type: str
+ description: iDRAC user password.
+ https_port:
+ type: int
+ description: iDRAC port.
+ 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: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ https_timeout:
+ description: The HTTPS socket level timeout in seconds.
+ type: int
+ default: 30
+ controller_id:
+ description:
+ - Fully Qualified Device Descriptor (FQDD) of the storage controller.
+ - For example- RAID.Slot.1-1.
+ - This option is mandatory when I(state) is C(present) while creating a volume.
+ type: str
+ volume_id:
+ description:
+ - FQDD of existing volume.
+ - For example- Disk.Virtual.4:RAID.Slot.1-1.
+ - This option is mandatory in the following scenarios,
+ - >-
+ I(state) is C(present), when updating a volume.
+ - >-
+ I(state) is C(absent), when deleting a volume.
+ - >-
+ I(command) is C(initialize), when initializing a volume.
+ type: str
+ state:
+ description:
+ - >-
+ C(present) creates a storage volume for the specified I (controller_id), or modifies the storage volume for the
+ specified I (volume_id).
+ "Note: Modification of an existing volume properties depends on drive and controller capabilities".
+ - C(absent) deletes the volume for the specified I(volume_id).
+ type: str
+ choices: [present, absent]
+ command:
+ description:
+ - C(initialize) initializes an existing storage volume for a specified I(volume_id).
+ type: str
+ choices: [initialize]
+ raid_type:
+ description:
+ - One of the following raid types must be selected to create a volume for firmware version 4.40 and above.
+ - C(RAID0) to create a RAID0 type volume.
+ - C(RAID1) to create a RAID1 type volume.
+ - C(RAID5) to create a RAID5 type volume.
+ - C(RAID6) to create a RAID6 type volume.
+ - C(RAID10) to create a RAID10 type volume.
+ - C(RAID50) to create a RAID50 type volume.
+ - C(RAID60) to create a RAID60 type volume.
+ type: str
+ choices: ["RAID0", "RAID1", "RAID5", "RAID6", "RAID10", "RAID50", "RAID60"]
+ name:
+ description:
+ - Name of the volume to be created.
+ - Only applicable when I(state) is C(present).
+ - This will be deprecated. Please use I(volume_name) for specifying the volume name.
+ type: str
+ volume_name:
+ description:
+ - Name of the volume to be created.
+ - Only applicable when I(state) is C(present).
+ type: str
+ drives:
+ description:
+ - FQDD of the Physical disks.
+ - For example- Disk.Bay.0:Enclosure.Internal.0-1:RAID.Slot.1-1.
+ - Only applicable when I(state) is C(present) when creating a new volume.
+ type: list
+ elements: str
+ block_size_bytes:
+ description:
+ - Block size in bytes.Only applicable when I(state) is C(present).
+ type: int
+ capacity_bytes:
+ description:
+ - Volume size in bytes.
+ - Only applicable when I(state) is C(present).
+ type: str
+ optimum_io_size_bytes:
+ description:
+ - Stripe size value must be in multiples of 64 * 1024.
+ - Only applicable when I(state) is C(present).
+ type: int
+ encryption_types:
+ description:
+ - The following encryption types can be selected.
+ - C(ControllerAssisted) The volume is encrypted by the storage controller entity.
+ - C(NativeDriveEncryption) The volume utilizes the native drive encryption capabilities
+ of the drive hardware.
+ - C(SoftwareAssisted) The volume is encrypted by the software running
+ on the system or the operating system.
+ - Only applicable when I(state) is C(present).
+ type: str
+ choices: [NativeDriveEncryption, ControllerAssisted, SoftwareAssisted]
+ encrypted:
+ description:
+ - Indicates whether volume is currently utilizing encryption or not.
+ - Only applicable when I(state) is C(present).
+ type: bool
+ oem:
+ description:
+ - Includes OEM extended payloads.
+ - Only applicable when I(state) is I(present).
+ type: dict
+ initialize_type:
+ description:
+ - Initialization type of existing volume.
+ - Only applicable when I(command) is C(initialize).
+ type: str
+ choices: [Fast, Slow]
+ default: Fast
+ job_wait:
+ description: Determines whether to wait for the job completion or not.
+ type: bool
+ default: true
+ job_wait_timeout:
+ description:
+ - The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.
+ - This option is applicable when I(job_wait) is C(True).
+ type: int
+ default: 1200
+ apply_time:
+ description:
+ - Apply time of the Volume configuration.
+ - C(Immediate) allows you to apply the volume configuration on the host server immediately and apply the changes. This is applicable for I(job_wait).
+ - C(OnReset) allows you to apply the changes on the next reboot of the host server.
+ - I(apply_time) has a default value based on the different types of the controller.
+ - For example, BOSS-S1 and BOSS-N1 controllers have a default value of I(apply_time) as C(OnReset).
+ - PERC controllers have a default value of I(apply_time) as C(Immediate).
+ type: str
+ choices: [Immediate, OnReset]
+ version_added: 8.5.0
+ reboot_server:
+ description:
+ - Reboot the server to apply the changes.
+ - I(reboot_server) is applicable only when I(apply_timeout) is C(OnReset) or
+ when the default value for the apply time of the controller is C(OnReset).
+ type: bool
+ default: false
+ version_added: 8.5.0
+ force_reboot:
+ description:
+ - Reboot the server forcefully to apply the changes when the normal reboot fails.
+ - I(force_reboot) is applicable only when I(reboot_server) is C(true).
+ type: bool
+ default: false
+ version_added: 8.5.0
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/main.yml
new file mode 100644
index 000000000..23e4223fa
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/meta/main.yml
@@ -0,0 +1,22 @@
+galaxy_info:
+ author: |
+ "Kritika-Bhateja
+ Lovepreet-Singh"
+ description: The role helps to manage the storage volume configuration.
+ company: Dell Technologies
+ license: GPL-3.0-only
+ min_ansible_version: "2.13"
+ platforms:
+ - name: EL
+ versions:
+ - "9"
+ - "8"
+ - name: Ubuntu
+ versions:
+ - jammy
+ - name: SLES
+ versions:
+ - "15SP3"
+ - "15SP4"
+ galaxy_tags: []
+dependencies: []
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/converge.yml
new file mode 100644
index 000000000..f7cbf1ba7
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/converge.yml
@@ -0,0 +1,83 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID0"
+ redfish_storage_volume_minimum_drives: 1
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: To check the behaviour of RAID0.
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID0/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/converge.yml
new file mode 100644
index 000000000..8f87e24e4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/converge.yml
@@ -0,0 +1,83 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID1"
+ redfish_storage_volume_minimum_drives: 2
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: To check the behaviour of Mirrored.
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID1/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/converge.yml
new file mode 100644
index 000000000..2e0749638
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/converge.yml
@@ -0,0 +1,83 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID10"
+ redfish_storage_volume_minimum_drives: 4
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: To check the behaviour of SpannedMirrors.
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID10/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/converge.yml
new file mode 100644
index 000000000..c4a5c2591
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/converge.yml
@@ -0,0 +1,83 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID5"
+ redfish_storage_volume_minimum_drives: 3
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: To check the behaviour of StripedWithParity.
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID5/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/converge.yml
new file mode 100644
index 000000000..ef22a880c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/converge.yml
@@ -0,0 +1,83 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID50"
+ redfish_storage_volume_minimum_drives: 6
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: To check the behaviour of SpannedStripesWithParity.
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID50/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/converge.yml
new file mode 100644
index 000000000..0963a5eb3
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/converge.yml
@@ -0,0 +1,80 @@
+---
+- name: TC-124007 - Ansible - Role- redfish_storage_volume - [Check Mode] [Idempotency] Validate creating RAID6 VD
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID6"
+ redfish_storage_volume_minimum_drives: 4
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for PERC, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_PERC"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID6/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/converge.yml
new file mode 100644
index 000000000..ae9e67945
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/converge.yml
@@ -0,0 +1,80 @@
+---
+- name: TC-124010 - Ansible - Role- redfish_storage_volume - [Check Mode] [Idempotency] Validate creating RAID60 VD
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID60"
+ redfish_storage_volume_minimum_drives: 8
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for PERC, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_PERC"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/RAID60/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__delete_virtual_drive.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__delete_virtual_drive.yml
new file mode 100644
index 000000000..df94bc905
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__delete_virtual_drive.yml
@@ -0,0 +1,33 @@
+---
+- name: Waiting for 10 seconds before fetching data
+ ansible.builtin.wait_for:
+ timeout: 10
+
+- name: Fetching Volume_id from iDRAC
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ url: "Systems/System.Embedded.1/Storage/{{ redfish_storage_volume_controller_id }}/Volumes"
+
+- name: Set fact for redfish_storage_volume_volume_id_list
+ ansible.builtin.set_fact:
+ redfish_storage_volume_volume_id_list: []
+
+- name: Extracting volume_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_volume_id_list: "{{ redfish_storage_volume_volume_id_list + [item['@odata.id'] | ansible.builtin.split('/') | last] }}"
+ loop: "{{ redfish_storage_volume_fetched_output.json.Members }}"
+
+- name: "Deleting virtual disk in {{ controller_id }}"
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: absent
+ volume_id: "{{ redfish_storage_volume_volume_id_list[0] }}"
+ reboot_server: true
+ job_wait: true
+ when: redfish_storage_volume_volume_id_list is defined and redfish_storage_volume_volume_id_list != []
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__extract_storage.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__extract_storage.yml
new file mode 100644
index 000000000..7be337e92
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__extract_storage.yml
@@ -0,0 +1,27 @@
+---
+- name: Fetching Storage controller from iDRAC
+ ansible.builtin.include_tasks:
+ file: ../__get_helper.yml
+ vars:
+ url: "Systems/System.Embedded.1/Storage?$expand=*($levels=1)"
+
+- name: Intializing set_fact variable
+ ansible.builtin.set_fact:
+ redfish_storage_volume_controller_id: ""
+ redfish_storage_volume_drive_list: []
+
+- name: Extracting Controller id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_controller_id: "{{ item.Id }}"
+ redfish_storage_volume_drive_list_odata: "{{ item.Drives }}"
+ when:
+ - redfish_storage_volume_search_in_name is defined and redfish_storage_volume_search_in_name in item.Name
+ - item.StorageControllers[0].SupportedRAIDTypes != []
+ - redfish_storage_volume_raid in item.StorageControllers[0].SupportedRAIDTypes
+ loop: "{{ redfish_storage_volume_fetched_output.json.Members }}"
+
+- name: Extracting Drives id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_drive_list: "{{ redfish_storage_volume_drive_list + [item['@odata.id'] | ansible.builtin.split('/') | last] }}"
+ loop: "{{ redfish_storage_volume_drive_list_odata }}"
+ when: redfish_storage_volume_drive_list_odata is defined
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__get_helper.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__get_helper.yml
new file mode 100644
index 000000000..ad8577667
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__get_helper.yml
@@ -0,0 +1,22 @@
+---
+- name: Waiting for LC status to be ready
+ ansible.builtin.include_tasks:
+ file: ../__lc_status.yml
+
+- name: Fetching data from iDRAC
+ ansible.builtin.uri:
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}/redfish/v1/{{ url }}"
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ method: GET
+ timeout: 30
+ body: {}
+ validate_certs: false
+ force_basic_auth: true
+ body_format: json
+ return_content: true
+ status_code: 200
+ headers: 'Accept=application/json'
+ register: redfish_storage_volume_fetched_output
+ when: url is defined
+ check_mode: false
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__idrac_reset.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__idrac_reset.yml
new file mode 100644
index 000000000..23f25ba5e
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__idrac_reset.yml
@@ -0,0 +1,23 @@
+---
+- name: GracefulRestart of iDRAC
+ ansible.builtin.import_role:
+ name: idrac_server_powerstate
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ reset_type: "GracefulRestart"
+ resource_id: "System.Embedded.1"
+
+- name: Waiting for 60 secs before LC tracking
+ ansible.builtin.wait_for:
+ timeout: 60
+ when:
+ - not ansible_check_mode
+ - idrac_server_powerstate_out is defined
+ - idrac_server_powerstate_out.changed
+
+- name: Waiting for LC status to be ready
+ ansible.builtin.include_tasks:
+ file: ../__lc_status.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__lc_status.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__lc_status.yml
new file mode 100644
index 000000000..9145e05af
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/__lc_status.yml
@@ -0,0 +1,22 @@
+---
+- name: Waiting for iDRAC to be in ready state
+ ansible.builtin.uri:
+ user: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ timeout: 30
+ validate_certs: false
+ return_content: true
+ force_basic_auth: true
+ body_format: "json"
+ headers:
+ Content-Type: "application/json"
+ Accept: "application/json"
+ OData-Version: "4.0"
+ url: "https://{{ lookup('env', 'IDRAC_IP') }}/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
+ method: POST
+ body: {}
+ until: status_result.json.Status == "Ready"
+ register: status_result
+ check_mode: false
+ retries: 120
+ delay: 30
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/converge.yml
new file mode 100644
index 000000000..934d2fb92
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/converge.yml
@@ -0,0 +1,156 @@
+---
+- name: TC-123778 - Ansible - Role - redfish_storage_volume - [Check Mode] [Idempotency] Validate creating RAID1 with apply_time with default values
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID1"
+ redfish_storage_volume_minimum_drives: 2
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for PERC, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_PERC"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Fetching data from iDRAC for BOSS
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'BOSS'
+
+ - name: Setting BOSS controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_boss_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for BOSS Controller
+ when: redfish_storage_volume_boss_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for BOSS, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_BOSS"
+ controller_id: "{{ redfish_storage_volume_boss_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ job_wait: false
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Waiting for idrac reset and LC tracking.
+ ansible.builtin.include_tasks:
+ file: ../__idrac_reset.yml
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Successfully submitted create volume task."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for BOSS
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'BOSS': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
+
+ - name: Executing if both PERC and BOSS is not found.
+ ansible.builtin.debug:
+ msg: "iDRAC doesn't have PERC and BOSS raid controller."
+ when: redfish_storage_volume_perc_raid_controller_id is undefined and redfish_storage_volume_boss_raid_controller_id is undefined
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_default/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/converge.yml
new file mode 100644
index 000000000..abdb4792b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/converge.yml
@@ -0,0 +1,133 @@
+---
+- name: TC-123862 - Ansible - Role- redfish_storage_volume - [Check Mode] [Idempotency] Validate creating RAID1 with apply_time as Immediate
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID1"
+ redfish_storage_volume_minimum_drives: 2
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for PERC, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_PERC"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ optimum_io_size_bytes: 65536
+ apply_time: "Immediate"
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Fetching data from iDRAC for BOSS
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'BOSS'
+
+ - name: Setting BOSS controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_boss_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for BOSS Controller
+ when: redfish_storage_volume_boss_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "TC-123865 - Ansible - Role - redfish_storage_volume - Provide invalid value to apply_time"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_BOSS"
+ controller_id: "{{ redfish_storage_volume_boss_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ apply_time: "Immediate"
+ job_wait: true
+ ignore_errors: true
+ register: redfish_storage_volume_result
+
+ - name: Asserting after performing operation for invalid apply_time for BOSS controller.
+ ansible.builtin.assert:
+ that:
+ - redfish_storage_volume_out.msg == "{{ error_msg }}"
+ vars:
+ error_msg: "Apply time Immediate is not supported. The supported values are ['OnReset']. Enter the valid values and retry the operation."
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
+
+ - name: Executing if both PERC and BOSS is not found.
+ ansible.builtin.debug:
+ msg: "iDRAC doesn't have PERC and BOSS raid controller."
+ when: redfish_storage_volume_perc_raid_controller_id is undefined and redfish_storage_volume_boss_raid_controller_id is undefined
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_immediate/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/converge.yml
new file mode 100644
index 000000000..167f475ee
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/converge.yml
@@ -0,0 +1,157 @@
+---
+- name: TC-123863 - [Check Mode] [Idempotency] Validate creating RAID1 with apply_time(OnReset) with reboot_server(true) with force_reboot(false)
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID1"
+ redfish_storage_volume_minimum_drives: 2
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for PERC, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_PERC"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ apply_time: "OnReset"
+ reboot_server: true
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ vars:
+ redfish_storage_volume_reset: true
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Fetching data from iDRAC for BOSS
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'BOSS'
+
+ - name: Setting BOSS controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_boss_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for BOSS Controller
+ when: redfish_storage_volume_boss_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for BOSS, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_BOSS"
+ controller_id: "{{ redfish_storage_volume_boss_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ apply_time: "OnReset"
+ reboot_server: true
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for BOSS
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'BOSS': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
+
+ - name: Executing if both PERC and BOSS is not found.
+ ansible.builtin.debug:
+ msg: "iDRAC doesn't have PERC and BOSS raid controller."
+ when: redfish_storage_volume_perc_raid_controller_id is undefined and redfish_storage_volume_boss_raid_controller_id is undefined
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/converge.yml
new file mode 100644
index 000000000..71014f248
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/converge.yml
@@ -0,0 +1,157 @@
+---
+- name: TC-123864 - [Check Mode] [Idempotency] Validate creating RAID1 with apply_time(OnReset) with reboot_server(true) with force_reboot(true)
+ hosts: all
+ vars:
+ redfish_storage_volume_failure: {}
+ redfish_storage_volume_raid: "RAID1"
+ redfish_storage_volume_minimum_drives: 2
+ gather_facts: false
+
+ tasks:
+ - name: Fetching data from iDRAC for PERC
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'PERC'
+
+ - name: Setting PERC controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_perc_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for PERC Controller
+ when: redfish_storage_volume_perc_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for PERC, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_PERC"
+ controller_id: "{{ redfish_storage_volume_perc_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ apply_time: "OnReset"
+ reboot_server: true
+ force_reboot: true
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for PERC
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'PERC': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Fetching data from iDRAC for BOSS
+ ansible.builtin.include_tasks:
+ file: ../__extract_storage.yml
+ vars:
+ redfish_storage_volume_search_in_name: 'BOSS'
+
+ - name: Setting BOSS controller_id
+ ansible.builtin.set_fact:
+ redfish_storage_volume_boss_raid_controller_id: "{{ redfish_storage_volume_controller_id }}"
+ when: redfish_storage_volume_controller_id != ""
+
+ - name: Running for BOSS Controller
+ when: redfish_storage_volume_boss_raid_controller_id is defined
+ block:
+ - name: "Checking minimum number of drives for {{ redfish_storage_volume_raid }}"
+ ansible.builtin.debug:
+ msg: "Minimum number of required drives: {{ redfish_storage_volume_minimum_drives }}, current: {{ redfish_storage_volume_drive_list | length }}"
+ when: redfish_storage_volume_drive_list | length < redfish_storage_volume_minimum_drives
+ failed_when: true
+
+ - name: "Create a volume for BOSS, raid_type {{ redfish_storage_volume_raid }}"
+ ansible.builtin.import_role:
+ name: dellemc.openmanage.redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ raid_type: "{{ redfish_storage_volume_raid }}"
+ volume_name: "VD_BOSS"
+ controller_id: "{{ redfish_storage_volume_boss_raid_controller_id }}"
+ drives: "{{ redfish_storage_volume_drive_list[:redfish_storage_volume_minimum_drives] }}"
+ apply_time: "OnReset"
+ reboot_server: true
+ force_reboot: true
+ job_wait: true
+
+ - name: Asserting operation with check mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Changes found to be applied."
+ when: ansible_check_mode
+
+ - name: Asserting operation with normal mode.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "The job is successfully completed."
+ when: not ansible_check_mode and redfish_storage_volume_out.changed
+
+ - name: Asserting operation with idempotence.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "No changes found to be applied."
+ when: not ansible_check_mode and not redfish_storage_volume_out.changed
+
+ rescue:
+ - name: Set the failure messages for BOSS
+ ansible.builtin.set_fact:
+ redfish_storage_volume_failure: "{{ redfish_storage_volume_failure | combine({'BOSS': {'msg': ansible_failed_result.msg,
+ 'failed_task_name': ansible_failed_task.name}}) }}"
+
+ always:
+ - name: Deleting VD
+ ansible.builtin.include_tasks:
+ file: ../__delete_virtual_drive.yml
+ when:
+ - not ansible_check_mode
+ - redfish_storage_volume_out is defined
+ - not redfish_storage_volume_out.changed
+
+ - name: Collecting failure
+ ansible.builtin.debug:
+ var: redfish_storage_volume_failure
+ when: redfish_storage_volume_failure
+ failed_when: true
+
+ - name: Executing if both PERC and BOSS is not found.
+ ansible.builtin.debug:
+ msg: "iDRAC doesn't have PERC and BOSS raid controller."
+ when: redfish_storage_volume_perc_raid_controller_id is undefined and redfish_storage_volume_boss_raid_controller_id is undefined
+ failed_when: true
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/molecule.yml
new file mode 100644
index 000000000..ed97d539c
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/apply_time_onreset_reboot_server_true_force_reboot_true/molecule.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/converge.yml
new file mode 100644
index 000000000..72b2e5977
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/converge.yml
@@ -0,0 +1,132 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+
+ tasks:
+ - name: To check the behaviour of invalid hostname.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'INVALID_IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ volume_type: "NonRedundant"
+ name: "VD" # noqa: var-naming[no-reserved]
+ controller_id: "{{ lookup('env', 'CONTROLLER_ID') }}"
+ drives: "{{ lookup('env', 'PHYSICAL_DISK') }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: false
+ ignore_errors: true
+ register: redfish_storage_volume_result
+
+ - name: Asserting after performing operation.
+ ansible.builtin.assert:
+ that: |-
+ redfish_storage_volume_out.msg == "<urlopen error [Errno -2] Name or service not known>"
+
+ - name: To check the behaviour of invalid credentials.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'INVALID_IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ volume_type: "NonRedundant"
+ name: "VD" # noqa: var-naming[no-reserved]
+ controller_id: "{{ lookup('env', 'CONTROLLER_ID') }}"
+ drives: "{{ lookup('env', 'PHYSICAL_DISK') }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: false
+ ignore_errors: true
+ register: redfish_storage_volume_result
+
+ - name: Asserting after performing operation for invalid credentials.
+ ansible.builtin.assert:
+ that: |-
+ redfish_storage_volume_out.msg == "HTTP Error 401: Unauthorized"
+
+ - name: To check the behaviour of invalid span count.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ volume_type: "SpannedStripesWithParity"
+ name: "VD" # noqa: var-naming[no-reserved]
+ controller_id: "{{ lookup('env', 'CONTROLLER_ID') }}"
+ drives: "{{ lookup('env', 'PHYSICAL_DISK') }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: false
+ ignore_errors: true
+ register: redfish_storage_volume_result
+
+ - name: Asserting after performing operation for invalid span count.
+ ansible.builtin.assert:
+ that: |-
+ redfish_storage_volume_out.msg == "HTTP Error 400: Bad Request"
+
+ - name: To check the behaviour of invalid certificate path.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: true
+ ca_path: "{{ lookup('env', 'INVALID_CERT_PATH') }}"
+ state: present
+ volume_type: "SpannedStripesWithParity"
+ name: "VD" # noqa: var-naming[no-reserved]
+ controller_id: "{{ lookup('env', 'CONTROLLER_ID') }}"
+ drives: "{{ lookup('env', 'PHYSICAL_DISK') }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: false
+ ignore_errors: true
+ register: redfish_storage_volume_result
+
+ - name: Asserting after performing operation for invalid certificate path.
+ ansible.builtin.assert:
+ that: |-
+ "certificate verify failed" in redfish_storage_volume_out.msg
+
+ - name: To check the behaviour of invalid volume type.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ state: present
+ volume_type: "InvalidMirrored"
+ name: "VD" # noqa: var-naming[no-reserved]
+ controller_id: "{{ lookup('env', 'CONTROLLER_ID') }}"
+ drives: "{{ lookup('env', 'PHYSICAL_DISK') }}"
+ capacity_bytes: 214748364800
+ optimum_io_size_bytes: 65536
+ encrypted: false
+ job_wait: false
+ ignore_errors: true
+ register: redfish_storage_volume_result
+
+ - name: Asserting after performing operation for invalid volume type.
+ ansible.builtin.assert:
+ that: |-
+ redfish_storage_volume_out.msg == "value of volume_type must be one of: NonRedundant, Mirrored,
+ StripedWithParity, SpannedMirrors, SpannedStripesWithParity, got: InvalidMirrored"
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/default/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/converge.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/converge.yml
new file mode 100644
index 000000000..a76faebd4
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/converge.yml
@@ -0,0 +1,55 @@
+---
+- name: Converge
+ hosts: all
+ gather_facts: false
+
+ tasks:
+ - name: To check the behaviour of Initialization type Fast.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ command: initialize
+ volume_id: "{{ lookup('env', 'INVALID_VOLUME_ID') }}"
+ initialize_type: "Fast"
+ ignore_errors: true
+ register: redfish_storage_volume_result
+
+ - name: Asserting operation for initialization of type Fast.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Specified Volume Id Disk.Virtual.0:RAID.Mezzanine.1C-1-test does not exist in the System."
+
+ - name: To check the behaviour of Initialization type Fast.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ command: initialize
+ volume_id: "{{ lookup('env', 'VOLUME_ID') }}"
+ initialize_type: "Fast"
+
+ - name: Asserting operation for initialization type Fast.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Successfully submitted initialize volume task."
+
+ - name: To check the behaviour of Initialization type Slow.
+ ansible.builtin.import_role:
+ name: redfish_storage_volume
+ vars:
+ hostname: "{{ lookup('env', 'IDRAC_IP') }}"
+ username: "{{ lookup('env', 'IDRAC_USER') }}"
+ password: "{{ lookup('env', 'IDRAC_PASSWORD') }}"
+ validate_certs: false
+ command: initialize
+ volume_id: "{{ lookup('env', 'VOLUME_ID') }}"
+ initialize_type: "Slow"
+
+ - name: Asserting operation for initialization type Slow.
+ ansible.builtin.assert:
+ that: redfish_storage_volume_out.msg == "Successfully submitted initialize volume task."
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/molecule.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/molecule.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/molecule/initialization/molecule.yml
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tasks/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tasks/main.yml
new file mode 100644
index 000000000..a6e2ff305
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tasks/main.yml
@@ -0,0 +1,34 @@
+---
+# tasks file for redfish_storage_volume
+- name: Setting up parameters
+ ansible.builtin.set_fact:
+ redfish_storage_volume_baseuri: "{{ hostname }}:{{ https_port }}"
+
+- name: Performing the operation on redfish storage volume
+ dellemc.openmanage.redfish_storage_volume:
+ baseuri: "{{ redfish_storage_volume_baseuri }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ timeout: "{{ https_timeout }}"
+ validate_certs: "{{ validate_certs }}"
+ ca_path: "{{ ca_path | default(omit) }}"
+ state: "{{ state | default(omit) }}"
+ controller_id: "{{ controller_id | default(omit) }}"
+ raid_type: "{{ raid_type | default(omit) }}"
+ drives: "{{ drives | default([]) }}"
+ volume_name: "{{ volume_name | default(name) | default(omit) }}"
+ volume_id: "{{ volume_id | default(omit) }}"
+ initialize_type: "{{ initialization_type | default(omit) }}"
+ command: "{{ command | default(omit) }}"
+ encryption_types: "{{ encryption_types | default(omit) }}"
+ encrypted: "{{ encrypted | default(omit) }}"
+ block_size_bytes: "{{ block_size_bytes | default(omit) }}"
+ capacity_bytes: "{{ capacity_bytes | default(omit) }}"
+ optimum_io_size_bytes: "{{ optimum_io_size_bytes | default(omit) }}"
+ apply_time: "{{ apply_time | default(omit) }}"
+ reboot_server: "{{ reboot_server | default(omit) }}"
+ force_reboot: "{{ force_reboot | default(omit) }}"
+ job_wait: "{{ job_wait | default(omit) }}"
+ job_wait_timeout: "{{ job_wait_timeout | default(omit) }}"
+ register: redfish_storage_volume_out
+ delegate_to: "{{ redfish_storage_volume_delegate }}"
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/inventory b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/test.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/test.yml
new file mode 100644
index 000000000..e392bcf21
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: Executing redfish storage volume
+ hosts: localhost
+ remote_user: root
+ roles:
+ - redfish_storage_volume
diff --git a/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/vars/main.yml b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/vars/main.yml
new file mode 100644
index 000000000..b3717db2b
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/roles/redfish_storage_volume/vars/main.yml
@@ -0,0 +1,4 @@
+---
+# vars file for redfish_storage_volume
+redfish_storage_volume_polling_interval: 30
+redfish_storage_volume_delegate: "{{ lookup('ansible.builtin.env', 'RUNON', default='localhost') }}"