Browse Source

Issue #375: Provision PowerEdge iDRAC Servers

Signed-off-by: abhishek-s-a <a_sa@dellteam.com>
Lucas A. Wilson 3 years ago
parent
commit
1d39779e1f
36 changed files with 2209 additions and 421 deletions
  1. 54 0
      control_plane/roles/control_plane_customiso/files/add_nfs_client.yml
  2. 56 0
      control_plane/roles/control_plane_customiso/files/temp_centos7.cfg
  3. 46 0
      control_plane/roles/control_plane_customiso/tasks/check_prerequisites.yml
  4. 64 0
      control_plane/roles/control_plane_customiso/tasks/create_unattended_iso.yml
  5. 112 0
      control_plane/roles/control_plane_customiso/tasks/edit_iso_config.yml
  6. 11 5
      control_plane/roles/control_plane_customiso/tasks/main.yml
  7. 33 0
      control_plane/roles/control_plane_customiso/vars/main.yml
  8. 13 0
      control_plane/roles/provision_idrac/files/temp_scp.xml
  9. 156 0
      control_plane/roles/provision_idrac/tasks/check_prerequisites.yml
  10. 58 0
      control_plane/roles/provision_idrac/tasks/create_vd.yml
  11. 52 0
      control_plane/roles/provision_idrac/tasks/deploy_os.yml
  12. 42 0
      control_plane/roles/provision_idrac/tasks/fetch_idrac_credentials.yml
  13. 119 0
      control_plane/roles/provision_idrac/tasks/import_scp.yml
  14. 25 13
      control_plane/roles/provision_idrac/tasks/main.yml
  15. 102 0
      control_plane/roles/provision_idrac/tasks/validate_idrac_vars.yml
  16. 49 0
      control_plane/roles/provision_idrac/vars/main.yml
  17. 37 0
      control_plane/roles/webui_awx/files/awx.yml
  18. 18 0
      control_plane/roles/webui_awx/files/awx_ee.yml
  19. 531 0
      control_plane/roles/webui_awx/files/awx_operator.yml
  20. 15 0
      control_plane/roles/webui_awx/files/awx_postgres_pv.yml
  21. 29 0
      control_plane/roles/webui_awx/files/awx_projects_pv.yml
  22. 5 0
      control_plane/roles/webui_awx/files/requirements.yml
  23. 118 270
      control_plane/roles/webui_awx/tasks/awx_configuration.yml
  24. 71 0
      control_plane/roles/webui_awx/tasks/configure_settings.yml
  25. 77 45
      control_plane/roles/webui_awx/tasks/install_awx.yml
  26. 6 42
      control_plane/roles/webui_awx/tasks/main.yml
  27. 50 46
      control_plane/roles/webui_awx/vars/main.yml
  28. 21 0
      control_plane/tools/idrac_secure_boot.yml
  29. 21 0
      control_plane/tools/idrac_system_lockdown.yml
  30. 41 0
      control_plane/tools/roles/idrac_secure_boot/tasks/configure_secure_boot.yml
  31. 20 0
      control_plane/tools/roles/idrac_secure_boot/tasks/main.yml
  32. 20 0
      control_plane/tools/roles/idrac_secure_boot/vars/main.yml
  33. 56 0
      control_plane/tools/roles/idrac_system_lockdown/tasks/check_prerequisites.yml
  34. 41 0
      control_plane/tools/roles/idrac_system_lockdown/tasks/configure_system_lockdown.yml
  35. 20 0
      control_plane/tools/roles/idrac_system_lockdown/tasks/main.yml
  36. 20 0
      control_plane/tools/roles/idrac_system_lockdown/vars/main.yml

+ 54 - 0
control_plane/roles/control_plane_customiso/files/add_nfs_client.yml

@@ -0,0 +1,54 @@
+#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+- name: Add nfs client entries
+  hosts: localhost
+  connection: local
+  gather_facts: false
+  tasks:
+    - name: Include control_plane_repo vars
+      include_vars: ../../control_plane_repo/vars/main.yml
+
+    - name: Check if idrac inventory file exists
+      stat:
+        path: "../../collect_device_info/files/idrac_inventory"
+      register: provisioned_file_result
+
+    - name: Check {{ exports_file_path }}
+      command: cat {{ exports_file_path }}
+      register: exports_file_check
+      changed_when: false
+      when: provisioned_file_result.stat.exists
+
+    - name: Adding NFS share entries in {{ exports_file_path }}
+      lineinfile:
+        path: "{{ exports_file_path }}"
+        line: "{{ nfs_share_offline_repo }} {{ item }}(rw,sync,no_root_squash)"
+      when:
+        - provisioned_file_result.stat.exists
+        - item not in exports_file_check.stdout
+      loop: "{{ lookup('file', '../../collect_device_info/files/idrac_inventory').splitlines() }}"
+
+    - name: Exporting the shared directories
+      command: /usr/sbin/exportfs -r
+      changed_when: true
+      when: provisioned_file_result.stat.exists
+
+    - name: Copy exports file to custom_iso role
+      copy:
+        src: "{{ exports_file_path }}"
+        dest: "{{ playbook_dir }}/exports"
+        mode: preserve
+      when: provisioned_file_result.stat.exists

+ 56 - 0
control_plane/roles/control_plane_customiso/files/temp_centos7.cfg

@@ -0,0 +1,56 @@
+# Install OS instead of upgrade
+install
+
+# SELinux configuration
+selinux --disabled
+
+# Firewall configuration
+firewall --disabled
+
+# text install
+text
+
+# Do not configure the X Window System
+skipx
+
+ignoredisk --only-use=sda
+
+# Keyboard layouts
+keyboard us
+
+# System language
+lang ks_language
+
+# Network information
+network  --bootproto=dhcp --device=ks_nic --onboot=on
+
+# Root password
+rootpw --iscrypted ks_password
+
+# System services
+services --enabled="chronyd"
+
+# System timezone
+timezone --utc ks_timezone
+
+# System bootloader configuration
+bootloader --location=mbr --boot-drive=sda
+
+# Partition clearing information
+clearpart --all --initlabel --drives=sda
+
+# Clear the Master Boot Record
+zerombr
+
+# Disk Partitioning
+partition /boot/efi --asprimary --fstype=vfat --label EFI  --size=200
+partition /boot     --asprimary --fstype=ext4 --label BOOT --size=500
+partition /         --asprimary --fstype=ext4 --label ROOT --size=4096 --grow
+
+# Reboot after installation
+reboot
+
+%packages
+@core
+net-tools
+%end

+ 46 - 0
control_plane/roles/control_plane_customiso/tasks/check_prerequisites.yml

@@ -0,0 +1,46 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Install genisoimage package
+  package:
+    name: genisoimage
+    state: present
+  tags: install
+
+- name: Install ansible-galaxy modules
+  command: ansible-galaxy collection install {{ item }}
+  changed_when: true
+  with_items:
+   - community.general
+   - dellemc.openmanage
+
+- name: Install omsdk using pip
+  pip:
+    name: omsdk
+    state: present
+  tags: install
+
+- name: Check iso mount folder
+  stat:
+    path: "{{ iso_mount_path }}{{ isolinux_cfg_path }}"
+  register: check_mount_iso
+  tags: install
+
+- name: Incorrect iso mount
+  fail:
+    msg: "{{ iso_mount_check_fail_msg }}"
+  when: not check_mount_iso.stat.exists
+  register: iso_mount_fail
+  tags: install

+ 64 - 0
control_plane/roles/control_plane_customiso/tasks/create_unattended_iso.yml

@@ -0,0 +1,64 @@
+#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+- name: Create custom ISO
+  command: >-
+    mkisofs -o {{ role_path }}/files/{{ unattended_iso_filename }} -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4
+    -boot-info-table -eltorito-alt-boot -e images/efiboot.img -no-emul-boot -J -R -V "CentOS 7 x86_64"  {{ tmp_iso_dir }}
+  changed_when: true
+  register: custom_iso_status
+  tags: install
+  args:
+    chdir: "{{ tmp_iso_dir }}"
+
+- name: Custom ISO creation status check
+  assert:
+    that:
+      - "'Total directory bytes:' in custom_iso_status.stderr"
+      - "'Path table size(bytes):' in custom_iso_status.stderr"
+      - "'Max brk space used' in custom_iso_status.stderr"
+      - "'extents written' in custom_iso_status.stderr"
+    success_msg: "{{ custom_iso_success_msg }}"
+    fail_msg: "{{ custom_iso_fail_msg }}"
+  register: iso_success_check
+
+- name: Remove the kickstart file
+  file:
+    path: "{{ role_path }}/files/{{ kickstart_file }}"
+    state: absent
+  tags: install
+
+- name: Include control_plane_repo vars
+  include_vars: ../../control_plane_repo/vars/main.yml
+
+- name: Copy ISO file to nfs share
+  copy:
+    src: "{{ role_path }}/files/{{ unattended_iso_filename }}"
+    dest: "{{ nfs_share_offline_repo }}/{{ unattended_iso_filename }}"
+    mode: preserve
+  tags: install
+
+- name: Fetch ansible-playbook location
+  command: whereis ansible-playbook
+  changed_when: false
+  register: ansible_playbook_location
+  tags: install
+
+- name: Schedule task
+  cron:
+    name: "Add idrac IP to nfs exports"
+    minute: "*/10"
+    job: "if ! out=`{{ ansible_playbook_location.stdout.split(' ')[1] }} {{ role_path }}/files/add_nfs_client.yml`; then echo $out >> {{ cron_error_log }}; fi"
+  tags: install

+ 112 - 0
control_plane/roles/control_plane_customiso/tasks/edit_iso_config.yml

@@ -0,0 +1,112 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+- name: Create iso directory
+  file:
+    path: "{{ tmp_iso_dir }}"
+    state: directory
+    mode: "{{ file_permission }}"
+  tags: install
+
+- name: Copy files to tmpiso folder
+  copy:
+    src: "{{ iso_mount_path }}"
+    dest: "{{ tmp_iso_dir }}"
+    mode: preserve
+  tags: install
+
+- name: Edit isolinux.cfg
+  replace:
+    path: "{{ tmp_iso_dir }}{{ isolinux_cfg_path }}"
+    regexp: "{{ item.regexp }}"
+    replace: "{{ item.replace }}"
+  with_items:
+      - { regexp: "append initrd=initrd.img", replace: "append initrd=initrd.img ks=cdrom:/{{ kickstart_file }}" }
+      - { regexp: "rd.live.check quiet", replace: "" }
+  tags: install
+
+- name: Edit grub.cfg
+  replace:
+    path: "{{ tmp_iso_dir }}{{ grub_cfg_path }}"
+    regexp: "{{ item.regexp }}"
+    replace: "{{ item.replace }}"
+  with_items:
+      - { regexp: "kernel /images/pxeboot/vmlinuz", replace: "kernel /images/pxeboot/vmlinuz ks=cdrom:/{{ kickstart_file }}" }
+      - { regexp: "linuxefi /images/pxeboot/vmlinuz", replace: "linuxefi /images/pxeboot/vmlinuz ks=cdrom:/{{ kickstart_file }}" }
+      - { regexp: "rd.live.check quiet", replace: "" }
+  tags: install
+
+- name: Remove the kickstart file if exists
+  file:
+    path: "{{ role_path }}/files/{{ kickstart_file }}"
+    state: absent
+  tags: install
+
+- name: Create the kickstart file
+  copy:
+    src: "{{ role_path }}/files/temp_centos7.cfg"
+    dest: "{{ role_path }}/files/{{ kickstart_file }}"
+    mode: "{{ file_permission }}"
+  tags: install
+
+- name: Random phrase generation
+  command: openssl rand -base64 12
+  changed_when: false
+  register: generate_random_phrase
+  tags: install
+  no_log: true
+
+- name: Encrypt login password
+  command: openssl passwd -1 -salt {{ generate_random_phrase.stdout }} {{ provision_password }}
+  no_log: true
+  changed_when: false
+  register: encrypt_login_pass
+  tags: install
+
+- name: Configure kickstart file - Password
+  replace:
+    path: "{{ role_path }}/files/{{ kickstart_file }}"
+    regexp: '^rootpw --iscrypted ks_password'
+    replace: 'rootpw --iscrypted {{ encrypt_login_pass.stdout }}'
+  no_log: true
+  tags: install
+
+- name: Configure kickstart file - nic
+  replace:
+    path: "{{ role_path }}/files/{{ kickstart_file }}"
+    regexp: '^network  --bootproto=dhcp --device=ks_nic --onboot=on'
+    replace: 'network  --bootproto=dhcp --device={{ host_network_nic }} --onboot=on'
+  tags: install
+
+- name: Configure kickstart file - timezone
+  replace:
+    path: "{{ role_path }}/files/{{ kickstart_file }}"
+    regexp: '^timezone --utc ks_timezone'
+    replace: 'timezone --utc {{ timezone }}'
+  tags: install
+
+- name: Configure kickstart file - language
+  replace:
+    path: "{{ role_path }}/files/{{ kickstart_file }}"
+    regexp: '^lang ks_language'
+    replace: 'lang {{ language }}'
+  tags: install
+
+- name: Copy kickstart file to iso mount path
+  copy:
+    src: "{{ role_path }}/files/{{ kickstart_file }}"
+    dest: "/tmp/tmpiso/{{ kickstart_file }}"
+    mode: preserve
+  tags: install

+ 11 - 5
control_plane/roles/control_plane_customiso/tasks/main.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -13,7 +13,13 @@
 #  limitations under the License.
 ---
 
-# Will be updated later in each PR
-- name: Pass
-  debug:
-    msg: "Pass"
+# tasks file for control_plane_customiso
+
+- name: Check iso mount path
+  include_tasks: check_prerequisites.yml
+
+- name: Edit iso config files
+  include_tasks: edit_iso_config.yml
+
+- name: Create unattended iso file
+  include_tasks: create_unattended_iso.yml

+ 33 - 0
control_plane/roles/control_plane_customiso/vars/main.yml

@@ -0,0 +1,33 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+# vars file for control_plane_customiso
+
+#Usage: check_prerequisites.yml
+iso_mount_path: /mnt/iso/
+iso_mount_check_fail_msg: "ISO file not mounted. Ensure /mnt/iso path is mounted with centos ISO file."
+
+#Usage: edit_iso_config.yml
+tmp_iso_dir: /tmp/tmpiso/
+kickstart_file: centos7.cfg
+file_permission: 0744
+isolinux_cfg_path: isolinux/isolinux.cfg
+grub_cfg_path: EFI/BOOT/grub.cfg
+
+#Usage: create_unattended_iso.yml
+unattended_iso_filename: unattended_centos7.iso
+custom_iso_success_msg: "Unattended ISO file created successfully"
+custom_iso_fail_msg: "Unattended ISO file creation failed. Ensure /mnt/iso path is mounted with valid centos minimal ISO file."
+cron_error_log: /var/log/nfs_cron_error.log

+ 13 - 0
control_plane/roles/provision_idrac/files/temp_scp.xml

@@ -0,0 +1,13 @@
+<SystemConfiguration>
+<Component FQDD="BIOS.Setup.1-1">
+  <Attribute Name="BootMode">Uefi</Attribute>
+  <Attribute Name="BootSeqRetry">Enabled</Attribute>
+</Component>
+<Component FQDD="iDRAC.Embedded.1">
+  <Attribute Name="SNMP.1#AgentEnable">Enabled</Attribute>
+  <Attribute Name="SNMP.1#TrapFormat">SNMPv1</Attribute>
+  <Attribute Name="SNMP.1#SNMPProtocol">All</Attribute>
+  <Attribute Name="SNMP.1#DiscoveryPort">161</Attribute>
+  <Attribute Name="SNMP.1#AlertPort">162</Attribute>
+</Component>
+</SystemConfiguration>

+ 156 - 0
control_plane/roles/provision_idrac/tasks/check_prerequisites.yml

@@ -0,0 +1,156 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Include control_plane_repo vars
+  include_vars: ../../control_plane_repo/vars/main.yml
+  run_once: true
+
+- name: Include custom_iso vars
+  include_vars: ../../control_plane_customiso/vars/main.yml
+  run_once: true
+
+- name: Check unattended ISO file
+  stat:
+    path: "{{ role_path }}/../control_plane_customiso/files/{{ unattended_iso_filename }}"
+  register: custom_iso_check
+  run_once: true
+
+- name: Custom ISO file not present
+  fail:
+    msg: "{{ custom_iso_check_fail_msg }}"
+  when: not custom_iso_check.stat.exists
+  register: custom_iso_fail
+
+- name: Adding NFS share entries in {{ exports_file_path }}
+  lineinfile:
+    path: "{{ exports_file_path }}"
+    line: "{{ nfs_share_offline_repo }} {{ inventory_hostname }}(rw,sync,no_root_squash)"
+  when: '"awx-" not in hostname.stdout'
+
+- name: Exporting the shared directories
+  command: exportfs -r
+  changed_when: true
+  when: '"awx-" not in hostname.stdout'
+  run_once: true
+
+- name: Check nfs exports file present
+  stat:
+    path: "{{ role_path }}/../control_plane_customiso/files/exports"
+  register: nfs_exports_present
+  when: '"awx-" in hostname.stdout'
+  run_once: true
+
+- name: Check nfs exports file content
+  command: cat "{{ role_path }}/../control_plane_customiso/files/exports"
+  changed_when: false
+  register: check_exports_path
+  run_once: true
+  when:
+    - '"awx-" in hostname.stdout'
+    - nfs_exports_present.stat.exists
+
+- name: Missing entries in nfs exports
+  fail:
+    msg: "{{ missing_exports_fail_msg }}"
+  when:
+    - '"awx-" in hostname.stdout'
+    - not nfs_exports_present.stat.exists or
+      check_exports_path.rc == 1 or
+      inventory_hostname not in check_exports_path.stdout
+
+- name: Fetch management station ip from exports file
+  shell: awk 'FNR==1' {{ role_path }}/../control_plane_customiso/files/exports | awk '{print $2}'
+  changed_when: false
+  register: fetch_public_ip
+  when: '"awx-" in hostname.stdout'
+
+- name: Set public ip
+  set_fact:
+    public_ip: "{{ fetch_public_ip.stdout.split(\"(\")[0] }}"
+  when: '"awx-" in hostname.stdout'
+
+- name: Initialize variables
+  set_fact:
+    raid_type: false
+    raid_controller_sensor: ""
+    raid_enclosure_name: ""
+    drives_id: ""
+    enterprise_license: false
+    datacenter_license: false
+    provision_status: false
+
+- name: Check provisioned_idrac_ip.yml file present
+  stat:
+    path: "{{ role_path }}/files/provisioned_idrac_ip.yml"
+  register: provisioned_file_present
+  run_once: true
+
+- name: Check idrac server is already provisioned
+  command: cat {{ role_path }}/files/provisioned_idrac_ip.yml
+  changed_when: false
+  register: check_provision_status
+  when: provisioned_file_present.stat.exists
+  run_once: true
+
+- name: Removing hosts already provisioned
+  fail:
+    msg: "{{ provision_fail_msg }}"
+  when:
+    - provisioned_file_present.stat.exists
+    - inventory_hostname in check_provision_status.stdout
+
+- name: Show status of the Lifecycle Controller
+  dellemc.openmanage.idrac_lifecycle_controller_status_info:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+  register: lc_check_status
+
+- name: LC not available
+  fail:
+    msg: "{{ lc_check_fail_msg }}"
+  when: not lc_check_status.lc_status_info.LCReady
+  register: lc_fail
+
+- name: Get system inventory
+  dellemc.openmanage.idrac_system_info:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+  register: idrac_info
+
+- name: Set enterprise license status
+  set_fact:
+    enterprise_license: true
+  with_items: "{{ idrac_info.system_info.License }}"
+  when:
+    - '"iDRAC" in idrac_info.system_info.License[my_idx1].LicenseDescription'
+    - '"Enterprise" in idrac_info.system_info.License[my_idx1].LicenseDescription'
+    - '"License" in idrac_info.system_info.License[my_idx1].LicenseDescription'
+    - '"Healthy" in idrac_info.system_info.License[my_idx1].PrimaryStatus'
+  loop_control:
+    index_var: my_idx1
+
+- name: Set datacenter license status
+  set_fact:
+    datacenter_license: true
+  with_items: "{{ idrac_info.system_info.License }}"
+  when:
+    - '"iDRAC" in idrac_info.system_info.License[my_idx2].LicenseDescription'
+    - '"Datacenter" in idrac_info.system_info.License[my_idx2].LicenseDescription'
+    - '"License" in idrac_info.system_info.License[my_idx2].LicenseDescription'
+    - '"Healthy" in idrac_info.system_info.License[my_idx2].PrimaryStatus'
+  loop_control:
+    index_var: my_idx2

+ 58 - 0
control_plane/roles/provision_idrac/tasks/create_vd.yml

@@ -0,0 +1,58 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Set RAID status
+  set_fact:
+    raid_type: true
+    raid_controller_sensor: "{{ idrac_info.system_info.ControllerSensor[my_idx3].FQDD }}"
+    raid_enclosure_name: "Enclosure.Internal.0-1:{{ idrac_info.system_info.ControllerSensor[my_idx3].FQDD }}"
+    raid_vd_status: "{{ idrac_info.system_info.VirtualDisk is defined and idrac_info.system_info.VirtualDisk[0].Name == \"omnia_vd\" }}"
+  with_items: "{{ idrac_info.system_info.Controller }}"
+  loop_control:
+    index_var: my_idx3
+  when: '"RAID" in idrac_info.system_info.ControllerSensor[my_idx3].FQDD'
+
+- name: View existing storage details
+  dellemc.openmanage.dellemc_idrac_storage_volume:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+    state: "view"
+  register: idrac_volume_list
+  when: raid_type and not raid_vd_status
+
+- name: Set drives details
+  set_fact:
+    drives_id: "{{ idrac_volume_list.storage_status.Message.Controller[raid_controller_sensor].Enclosure[raid_enclosure_name].PhysicalDisk }}"
+    drives_count: "{{ idrac_volume_list.storage_status.Message.Controller[raid_controller_sensor].Enclosure[raid_enclosure_name].PhysicalDisk | length }}"
+  when: raid_type and not raid_vd_status
+
+- name: Create VD
+  dellemc.openmanage.dellemc_idrac_storage_volume:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+    state: "create"
+    controller_id: "{{ raid_controller_sensor }}"
+    raid_reset_config: "True"
+    volume_type: "{{ raid_level }}"
+    raid_init_operation: "Fast"
+    volumes:
+      - name: "omnia_vd"
+        span_length: "{{ drives_count }}"
+        drives:
+          id: "{{ drives_id }}"
+  register: create_vd_status
+  when: raid_type and not raid_vd_status

+ 52 - 0
control_plane/roles/provision_idrac/tasks/deploy_os.yml

@@ -0,0 +1,52 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Set one-time boot device to PXE
+  community.general.redfish_command:
+    category: Systems
+    command: SetOneTimeBoot
+    bootdevice: "Pxe"
+    baseuri: "{{ inventory_hostname }}"
+    username: "{{ idrac_username }}"
+    password: "{{ idrac_password }}"
+  when: not (enterprise_license or datacenter_license)
+
+- name: Reboot server
+  dellemc.openmanage.redfish_powerstate:
+    baseuri: "{{ inventory_hostname }}"
+    username: "{{ idrac_username }}"
+    password: "{{ idrac_password }}"
+    reset_type: ForceRestart
+  when: not (enterprise_license or datacenter_license)
+  register: deploy_os
+
+- name: Install OS using iDRAC
+  dellemc.openmanage.idrac_os_deployment:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+    share_name: "{{ public_ip }}:{{ nfs_share_offline_repo }}"
+    iso_image: "{{ unattended_iso_filename }}"
+    expose_duration: "{{ expose_duration }}"
+  register: deploy_os
+  when: enterprise_license or datacenter_license
+
+- name: Add idrac ip to provisioned_idrac_ip.yml
+  lineinfile:
+    path: "{{ role_path }}/files/provisioned_idrac_ip.yml"
+    create: yes
+    mode: "{{ file_permission }}"
+    line: "{{ inventory_hostname }}"
+  when: not deploy_os.failed

+ 42 - 0
control_plane/roles/provision_idrac/tasks/fetch_idrac_credentials.yml

@@ -0,0 +1,42 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Check if {{ login_input_filename }} file is encrypted
+  command: cat {{ login_input_filename }}
+  changed_when: false
+  no_log: true
+  register: config_content
+  run_once: true
+
+- name: Decrpyt {{ login_input_filename }}
+  command: >-
+    ansible-vault decrypt {{ login_input_filename }}
+    --vault-password-file {{ login_vault_filename }}
+  when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+  changed_when: false
+  run_once: true
+
+- name: Include variable file {{ login_input_filename }}
+  include_vars: "{{ login_input_filename }}"
+  no_log: true
+  run_once: true
+
+- name: Encrypt {{ login_input_filename }}
+  command: >-
+    ansible-vault encrypt {{ login_input_filename }}
+    --vault-password-file {{ login_vault_filename }}
+  changed_when: false
+  when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+  run_once: true

+ 119 - 0
control_plane/roles/provision_idrac/tasks/import_scp.yml

@@ -0,0 +1,119 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Remove the scp file if exists
+  file:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    state: absent
+  run_once: true
+
+- name: Create scp file
+  copy:
+    src: "{{ role_path }}/files/temp_scp.xml"
+    dest: "{{ role_path }}/files/{{ scp_filename }}"
+    mode: preserve
+  run_once: true
+
+- name: Add system profile value Performance to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: '  <Attribute Name="SysProfile">PerfOptimized</Attribute>'
+    insertafter: '^(.*)BootSeqRetry'
+  when: idrac_system_profile == "Performance"
+  run_once: true
+
+- name: Add system profile value PerformancePerWatt(OS) to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: '  <Attribute Name="SysProfile">PerfPerWattOptimizedOs</Attribute>'
+    insertafter: '^(.*)BootSeqRetry'
+  when: idrac_system_profile == "PerformancePerWatt(OS)"
+  run_once: true
+
+- name: Add system profile value PerformancePerWatt(DAPC) to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: '  <Attribute Name="SysProfile">PerfPerWattOptimizedDapc</Attribute>'
+    insertafter: '^(.*)BootSeqRetry'
+  when: idrac_system_profile == "PerformancePerWatt(DAPC)"
+  run_once: true
+
+- name: Add system profile value WorkstationPerformance to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: '  <Attribute Name="SysProfile">PerfWorkStationOptimized</Attribute>'
+    insertafter: '^(.*)BootSeqRetry'
+  when: idrac_system_profile == "WorkstationPerformance"
+  run_once: true
+
+- name: Add PXE attributes to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: "{{ item }}"
+    insertafter: '^(.*)SysProfile'
+    with_items:
+      - '  <Attribute Name="PxeDev1VlanPriority">0</Attribute>'
+      - '  <Attribute Name="PxeDev1Interface">NIC.Integrated.1-1-1</Attribute>'
+      - '  <Attribute Name="PxeDev1VlanId">1</Attribute>'
+      - '  <Attribute Name="PxeDev1VlanEnDis">Enabled</Attribute>'
+      - '  <Attribute Name="PxeDev1Protocol">IPv4</Attribute>'
+      - '  <Attribute Name="PxeDev1EnDis">Enabled</Attribute>'
+  when: not (enterprise_license or datacenter_license)
+  run_once: true
+
+- name: Disable PXE attributes to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: '  <Attribute Name="PxeDev1EnDis">Disabled</Attribute>'
+    insertafter: '^(.*)SysProfile'
+  when: enterprise_license or datacenter_license
+  run_once: true
+
+- name: Add SNMP community name attribute to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: '  <Attribute Name="SNMP.1#AgentCommunity">{{ snmp_community_name }}</Attribute>'
+    insertafter: '^(.*)SNMP.1#AgentEnable'
+  run_once: true
+
+- name: Add SNMP trap destination attributes to scp file
+  lineinfile:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    line: "{{ item }}"
+    insertafter: '^(.*)SNMP.1#AlertPort'
+  with_items:
+    - '  <Attribute Name="SNMPAlert.1#Destination">{{ snmp_trap_destination }}</Attribute>'
+    - '  <Attribute Name="SNMPAlert.1#State">Enabled</Attribute>'
+  when: snmp_trap_status
+  run_once: true
+
+- name: Import SCP from a local path and wait for this job to get completed
+  dellemc.openmanage.idrac_server_config_profile:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+    share_name: "{{ role_path }}/files/"
+    command: "import"
+    scp_file: "{{ scp_filename }}"
+    scp_components: "ALL"
+    shutdown_type: "Graceful"
+    job_wait: "True"
+  register: import_scp_status
+
+- name: Remove the scp file
+  file:
+    path: "{{ role_path }}/files/{{ scp_filename }}"
+    state: absent
+  run_once: true

+ 25 - 13
control_plane/roles/provision_idrac/tasks/main.yml

@@ -1,19 +1,31 @@
 # Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
 #
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#     http://www.apache.org/licenses/LICENSE-2.0
 #
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
 ---
 
-# Will be updated later in each PR
-- name: Pass
-  debug:
-    msg: "Pass"
+# tasks file for provision_idrac
+
+- name: Validate idrac parameters
+  include_tasks: validate_idrac_vars.yml
+
+- name: Check prerequisites
+  include_tasks: check_prerequisites.yml
+
+- name: Import SCP
+  include_tasks: import_scp.yml
+
+- name: Create VD
+  include_tasks: create_vd.yml
+
+- name: Deploy OS
+  include_tasks: deploy_os.yml

+ 102 - 0
control_plane/roles/provision_idrac/tasks/validate_idrac_vars.yml

@@ -0,0 +1,102 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Include variable file idrac_vars.yml
+  include_vars: "{{ idrac_input_filename }}"
+  run_once: true
+
+- name: Include variable file base_vars.yml
+  include_vars: "{{ base_input_filename }}"
+  run_once: true
+
+- name: Initialize variables
+  set_fact:
+    snmp_trap_status: false
+  run_once: true
+
+- name: Validate input parameters are not empty
+  fail:
+    msg: "{{ idrac_input_fail_msg }}"
+  register: idrac_config_check
+  when:
+    - idrac_system_profile | length < 1
+
+- name: Assert idrac_system_profile value
+  assert:
+    that:
+      - idrac_system_profile == "Performance" or idrac_system_profile == "PerformancePerWatt(DAPC)" or idrac_system_profile == "PerformancePerWatt(OS)" or idrac_system_profile == "WorkstationPerformance"
+    success_msg: "{{ idrac_system_profile_success_msg }}"
+    fail_msg: "{{ idrac_system_profile_fail_msg }}"
+
+- name: Assert firmware_update_required value
+  assert:
+    that:
+      - firmware_update_required == true or firmware_update_required == false
+    success_msg: "{{ firmware_update_success_msg }}"
+    fail_msg: "{{ firmware_update_fail_msg }}"
+
+- name: Assert snmp_community_name value
+  assert:
+    that:
+      - snmp_community_name | length > 1
+    success_msg: "{{ snmp_community_success_msg }}"
+    fail_msg: "{{ snmp_community_fail_msg }}"
+
+- name: Set snmp trap destination status
+  set_fact:
+    snmp_trap_status: true
+  when: snmp_trap_destination | length > 1
+  run_once: true
+
+- name: Assert snmp_trap_destination value
+  assert:
+    that:
+      - snmp_trap_destination | length > 6
+    success_msg: "{{ snmp_trap_dest_success_msg }}"
+    fail_msg: "{{ snmp_trap_dest_fail_msg }}"
+  when: snmp_trap_status
+
+- name: Check hostname
+  command: hostname
+  changed_when: false
+  register: hostname
+  run_once: true
+
+- name: Fetch the system public IP
+  set_fact:
+    public_ip: "{{ lookup('vars','ansible_'+public_nic).ipv4.address }}"
+  run_once: true
+  when: '"awx-" not in hostname.stdout'
+
+- name: Assert public IP
+  assert:
+    that:
+      - public_ip | length > 7
+      - public_ip | ipv4
+    success_msg: "{{ public_ip_success_msg }}"
+    fail_msg: "{{ public_ip_fail_msg }}"
+  when: '"awx-" not in hostname.stdout'
+
+- name: Fetch idrac credentials
+  include_tasks: fetch_idrac_credentials.yml
+  when: '"awx-" not in hostname.stdout'
+
+- name: Set idrac credentials
+  set_fact:
+    idrac_username: "{{ lookup('env','ANSIBLE_NET_USERNAME') }}"
+    idrac_password: "{{ lookup('env','ANSIBLE_NET_PASSWORD') }}"
+  no_log: true
+  when: '"awx-" in hostname.stdout'
+  run_once: true

+ 49 - 0
control_plane/roles/provision_idrac/vars/main.yml

@@ -0,0 +1,49 @@
+#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+# vars file for provision_idrac
+
+# Usage: validate_idrac_vars.yml
+idrac_input_filename: input_params/idrac_vars.yml
+base_input_filename: input_params/base_vars.yml
+login_input_filename: input_params/login_vars.yml
+login_vault_filename: input_params/.login_vault_key
+idrac_input_fail_msg: "Please provide all the required parameters in idrac_vars.yml"
+idrac_system_profile_success_msg: "idrac_system_profile validated"
+idrac_system_profile_fail_msg: "Failed. Incorrect setting input for idrac_system_profile in idrac_vars.yml"
+firmware_update_success_msg: "firmware_update_required validated"
+firmware_update_fail_msg: "Failed. firmware_update_required accepts only true or false in idrac_vars.yml"
+snmp_community_success_msg: "snmp_community_name validated"
+snmp_community_fail_msg: "Failed. snmp_community_name should not be empty in base_vars.yml"
+snmp_trap_dest_success_msg: "snmp_trap_destination validated"
+snmp_trap_dest_fail_msg: "Failed. Incorrect value for snmp_trap_destination in base_vars.yml"
+public_ip_success_msg: "public_ip validated"
+public_ip_fail_msg: "Failed. Incorrect value for public_nic in base_vars.yml"
+
+# Usage: check_prerequisites.yml
+custom_iso_check_fail_msg: "Custom ISO file is not present in the device. Please run appliance.yml first to create custom iso file unattended_centos7.iso"
+missing_exports_fail_msg: "Missing iDRAC IP entry in /etc/exports file. Wait for 10 minutes and retry again"
+lc_check_fail_msg: "LC is not ready. Retry again after LC is ready"
+provision_fail_msg: "Skipping remaining tasks for already provisioned servers. To provision server again remove iDRAC IP from the file control_plane/roles/provision_idrac/files/provisioned_idrac_ip.yml"
+
+# Usage: import_scp.yml
+scp_filename: idrac_scp.yml
+
+# Usage: create_vd.yml
+raid_level: "RAID 0"
+
+# Usage: deploy_os.yml
+expose_duration: 60
+file_permission: 0644

+ 37 - 0
control_plane/roles/webui_awx/files/awx.yml

@@ -0,0 +1,37 @@
+---
+apiVersion: awx.ansible.com/v1beta1
+kind: AWX
+metadata:
+  name: awx
+  namespace: awx
+spec:
+  deployment_type: awx
+
+  #tower_hostname:
+  #tower_secret_key_secret:
+
+  #tower_extra_volumes:
+
+  #tower_admin_user: admin
+  #tower_admin_email:
+  #tower_admin_password_secret:
+
+  tower_ingress_type: Ingress
+  #tower_ingress_type:
+  #tower_loadbalancer_protocol:
+  #tower_loadbalancer_port:
+
+  #tower_image_pull_secret:
+
+  tower_postgres_storage_class: nfs-client
+
+  tower_projects_persistence: true
+  tower_projects_use_existing_claim: "_Yes_"
+  tower_projects_existing_claim: awx-pv-claim
+  tower_projects_storage_class: manual
+  tower_projects_storage_size: 10Gi
+  tower_projects_storage_access_mode: RWO
+
+  tower_ee_images:
+    - name: custom-awx-ee
+      image: localhost/custom-awx-ee

+ 18 - 0
control_plane/roles/webui_awx/files/awx_ee.yml

@@ -0,0 +1,18 @@
+FROM quay.io/ansible/awx-ee:0.2.0
+
+USER root
+
+# add Ansible galaxy dependencies
+ADD requirements.yml /tmp/requirements.yml
+
+# install omsdk
+RUN pip install omsdk --upgrade
+
+# install Ansible Galaxy collections
+RUN ansible-galaxy collection install -r /tmp/requirements.yml --collections-path /usr/share/ansible/collections
+
+# add certificates
+RUN update-ca-trust force-enable
+RUN chmod -R 0777 /usr/share/ansible/collections
+
+USER 1000

+ 531 - 0
control_plane/roles/webui_awx/files/awx_operator.yml

@@ -0,0 +1,531 @@
+# This file is generated by Ansible. Changes will be lost.
+# Update templates under ansible/templates/
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: awxs.awx.ansible.com
+  namespace: awx
+spec:
+  group: awx.ansible.com
+  names:
+    kind: AWX
+    listKind: AWXList
+    plural: awxs
+    singular: awx
+  scope: Namespaced
+  versions:
+    - name: v1beta1
+      served: true
+      storage: true
+      subresources:
+        status: {}
+      schema:
+        openAPIV3Schema:
+          description: Schema validation for the AWX CRD
+          properties:
+            spec:
+              properties:
+                deployment_type:
+                  description: Name of the deployment type
+                  type: string
+                  default: awx
+                kind:
+                  description: Kind of the deployment type
+                  type: string
+                  default: AWX
+                api_version:
+                  description: apiVersion of the deployment type
+                  type: string
+                  default: awx.ansible.com/v1beta1
+                tower_task_privileged:
+                  description: If a privileged security context should be enabled
+                  type: boolean
+                  default: false
+                tower_admin_user:
+                  description: Username to use for the admin account
+                  type: string
+                  default: admin
+                tower_hostname:
+                  description: The hostname of the instance
+                  type: string
+                tower_admin_email:
+                  description: The admin user email
+                  type: string
+                tower_admin_password_secret:
+                  description: Secret where the admin password can be found
+                  type: string
+                tower_postgres_configuration_secret:
+                  description: Secret where the database configuration can be found
+                  type: string
+                tower_old_postgres_configuration_secret:
+                  description: Secret where the old database configuration can be found for data migration
+                  type: string
+                tower_secret_key_secret:
+                  description: Secret where the secret key can be found
+                  type: string
+                tower_broadcast_websocket_secret:
+                  description: Secret where the broadcast websocket secret can be found
+                  type: string
+                tower_extra_volumes:
+                  description: Specify extra volumes to add to the application pod
+                  type: string
+                tower_ingress_type:
+                  description: The ingress type to use to reach the deployed instance
+                  type: string
+                  enum:
+                    - none
+                    - Ingress
+                    - ingress
+                    - Route
+                    - route
+                    - LoadBalancer
+                    - loadbalancer
+                    - NodePort
+                    - nodeport
+                tower_ingress_annotations:
+                  description: Annotations to add to the ingress
+                  type: string
+                tower_ingress_tls_secret:
+                  description: Secret where the ingress TLS secret can be found
+                  type: string
+                tower_loadbalancer_annotations:
+                  description: Annotations to add to the loadbalancer
+                  type: string
+                tower_loadbalancer_protocol:
+                  description: Protocol to use for the loadbalancer
+                  type: string
+                  default: http
+                  enum:
+                    - http
+                    - https
+                tower_loadbalancer_port:
+                  description: Port to use for the loadbalancer
+                  type: integer
+                  default: 80
+                tower_route_host:
+                  description: The DNS to use to points to the instance
+                  type: string
+                tower_route_tls_termination_mechanism:
+                  description: The secure TLS termination mechanism to use
+                  type: string
+                  default: Edge
+                  enum:
+                    - Edge
+                    - edge
+                    - Passthrough
+                    - passthrough
+                tower_route_tls_secret:
+                  description: Secret where the TLS related credentials are stored
+                  type: string
+                tower_node_selector:
+                  description: nodeSelector for the AWX pods
+                  type: string
+                tower_tolerations:
+                  description: node tolerations for the AWX pods
+                  type: string
+                tower_image:
+                  description: Registry path to the application container to use
+                  type: string
+                tower_image_version:
+                  description: Application container image version to use
+                  type: string
+                tower_ee_images:
+                  description: Registry path to the Execution Environment container to use
+                  type: array
+                  items:
+                    type: object
+                    properties:
+                      name:
+                        type: string
+                      image:
+                        type: string
+                tower_image_pull_policy:
+                  description: The image pull policy
+                  type: string
+                  default: IfNotPresent
+                  enum:
+                    - Always
+                    - always
+                    - Never
+                    - never
+                    - IfNotPresent
+                    - ifnotpresent
+                tower_image_pull_secret:
+                  description: The image pull secret
+                  type: string
+                tower_task_resource_requirements:
+                  description: Resource requirements for the task container
+                  properties:
+                    requests:
+                      properties:
+                        cpu:
+                          type: string
+                        memory:
+                          type: string
+                        storage:
+                          type: string
+                      type: object
+                    limits:
+                      properties:
+                        cpu:
+                          type: string
+                        memory:
+                          type: string
+                        storage:
+                          type: string
+                      type: object
+                  type: object
+                tower_web_resource_requirements:
+                  description: Resource requirements for the web container
+                  properties:
+                    requests:
+                      properties:
+                        cpu:
+                          type: string
+                        memory:
+                          type: string
+                        storage:
+                          type: string
+                      type: object
+                    limits:
+                      properties:
+                        cpu:
+                          type: string
+                        memory:
+                          type: string
+                        storage:
+                          type: string
+                      type: object
+                  type: object
+                tower_replicas:
+                  description: Number of instance replicas
+                  type: integer
+                  default: 1
+                  format: int32
+                tower_garbage_collect_secrets:
+                  description: Whether or not to remove secrets upon instance removal
+                  default: false
+                  type: boolean
+                tower_create_preload_data:
+                  description: Whether or not to preload data upon Tower instance creation
+                  default: true
+                  type: boolean
+                tower_task_args:
+                  type: array
+                  items:
+                    type: string
+                tower_task_command:
+                  type: array
+                  items:
+                    type: string
+                tower_web_args:
+                  type: array
+                  items:
+                    type: string
+                tower_web_command:
+                  type: array
+                  items:
+                    type: string
+                tower_task_extra_env:
+                  type: string
+                tower_web_extra_env:
+                  type: string
+                tower_ee_extra_volume_mounts:
+                  description: Specify volume mounts to be added to Execution container
+                  type: string
+                tower_task_extra_volume_mounts:
+                  description: Specify volume mounts to be added to Task container
+                  type: string
+                tower_web_extra_volume_mounts:
+                  description: Specify volume mounts to be added to the Web container
+                  type: string
+                tower_redis_image:
+                  description: Registry path to the redis container to use
+                  type: string
+                tower_redis_image_version:
+                  description: Redis container image version to use
+                  type: string
+                tower_postgres_image:
+                  description: Registry path to the PostgreSQL container to use
+                  type: string
+                tower_postgres_image_version:
+                  description: PostgreSQL container image version to use
+                  type: string
+                tower_postgres_selector:
+                  description: nodeSelector for the Postgres pods
+                  type: string
+                tower_postgres_tolerations:
+                  description: node tolerations for the Postgres pods
+                  type: string
+                tower_postgres_storage_requirements:
+                  description: Storage requirements for the PostgreSQL container
+                  properties:
+                    requests:
+                      properties:
+                        storage:
+                          type: string
+                      type: object
+                    limits:
+                      properties:
+                        storage:
+                          type: string
+                      type: object
+                  type: object
+                tower_postgres_resource_requirements:
+                  description: Resource requirements for the PostgreSQL container
+                  properties:
+                    requests:
+                      properties:
+                        cpu:
+                          type: string
+                        memory:
+                          type: string
+                      type: object
+                    limits:
+                      properties:
+                        cpu:
+                          type: string
+                        memory:
+                          type: string
+                      type: object
+                  type: object
+                tower_postgres_storage_class:
+                  description: Storage class to use for the PostgreSQL PVC
+                  type: string
+                tower_postgres_data_path:
+                  description: Path where the PostgreSQL data are located
+                  type: string
+                ca_trust_bundle:
+                  description: Path where the trusted CA bundle is available
+                  type: string
+                development_mode:
+                  description: If the deployment should be done in development mode
+                  type: boolean
+                ldap_cacert_secret:
+                  description: Secret where can be found the LDAP trusted Certificate Authority Bundle
+                  type: string
+                tower_projects_persistence:
+                  description: Whether or not the /var/lib/projects directory will be persistent
+                  default: false
+                  type: boolean
+                tower_projects_use_existing_claim:
+                  description: Using existing PersistentVolumeClaim
+                  type: string
+                  enum:
+                    - _Yes_
+                    - _No_
+                tower_projects_existing_claim:
+                  description: PersistentVolumeClaim to mount /var/lib/projects directory
+                  type: string
+                tower_projects_storage_class:
+                  description: Storage class for the /var/lib/projects PersistentVolumeClaim
+                  type: string
+                tower_projects_storage_size:
+                  description: Size for the /var/lib/projects PersistentVolumeClaim
+                  default: 8Gi
+                  type: string
+                tower_projects_storage_access_mode:
+                  description: AccessMode for the /var/lib/projects PersistentVolumeClaim
+                  default: ReadWriteMany
+                  type: string
+                extra_settings:
+                  description: Extra settings to specify for the API
+                  items:
+                    properties:
+                      setting:
+                        type: string
+                      value:
+                        type: string
+                    type: object
+                  type: array
+              type: object
+            status:
+              properties:
+                towerURL:
+                  description: URL to access the deployed instance
+                  type: string
+                towerAdminUser:
+                  description: Admin user of the deployed instance
+                  type: string
+                towerAdminPasswordSecret:
+                  description: Admin password of the deployed instance
+                  type: string
+                towerMigratedFromSecret:
+                  description: The secret used for migrating an old Tower.
+                  type: string
+                towerVersion:
+                  description: Version of the deployed instance
+                  type: string
+                towerImage:
+                  description: URL of the image used for the deployed instance
+                  type: string
+                conditions:
+                  description: The resulting conditions when a Service Telemetry is instantiated
+                  items:
+                    properties:
+                      status:
+                        type: string
+                      type:
+                        type: string
+                      reason:
+                        type: string
+                      lastTransitionTime:
+                        type: string
+                    type: object
+                  type: array
+              type: object
+          type: object
+
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  creationTimestamp: null
+  name: awx-operator
+  namespace: awx
+rules:
+  - apiGroups:
+      - route.openshift.io
+    resources:
+      - routes
+      - routes/custom-host
+    verbs:
+      - '*'
+  - apiGroups:
+      - ""
+      - "rbac.authorization.k8s.io"
+    resources:
+      - pods
+      - services
+      - services/finalizers
+      - serviceaccounts
+      - endpoints
+      - persistentvolumeclaims
+      - events
+      - configmaps
+      - secrets
+      - roles
+      - rolebindings
+    verbs:
+      - '*'
+  - apiGroups:
+      - apps
+      - extensions
+    resources:
+      - deployments
+      - daemonsets
+      - replicasets
+      - statefulsets
+      - ingresses
+    verbs:
+      - '*'
+  - apiGroups:
+      - monitoring.coreos.com
+    resources:
+      - servicemonitors
+    verbs:
+      - get
+      - create
+  - apiGroups:
+      - apps
+    resourceNames:
+      - awx-operator
+    resources:
+      - deployments/finalizers
+    verbs:
+      - update
+  - apiGroups:
+      - apps
+    resources:
+      - deployments/scale
+      - statefulsets/scale
+    verbs:
+      - patch
+  - apiGroups:
+      - ""
+    resources:
+      - pods/exec
+    verbs:
+      - create
+      - get
+  - apiGroups:
+      - apps
+    resources:
+      - replicasets
+    verbs:
+      - get
+  - apiGroups:
+      - awx.ansible.com
+    resources:
+      - '*'
+    verbs:
+      - '*'
+
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: awx-operator
+  namespace: awx
+subjects:
+  - kind: ServiceAccount
+    name: awx-operator
+    namespace: awx
+roleRef:
+  kind: ClusterRole
+  name: awx-operator
+  apiGroup: rbac.authorization.k8s.io
+
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: awx-operator
+  namespace: awx
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: awx-operator
+  namespace: awx
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      name: awx-operator
+  template:
+    metadata:
+      labels:
+        name: awx-operator
+    spec:
+      serviceAccountName: awx-operator
+      containers:
+        - name: awx-operator
+          image: "quay.io/ansible/awx-operator:0.9.0"
+          imagePullPolicy: "Always"
+          volumeMounts:
+            - mountPath: /tmp/ansible-operator/runner
+              name: runner
+          env:
+            # Watch all namespaces (cluster-scoped).
+            - name: WATCH_NAMESPACE
+              value: ""
+            - name: POD_NAME
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.name
+            - name: OPERATOR_NAME
+              value: awx-operator
+            - name: ANSIBLE_GATHERING
+              value: explicit
+          livenessProbe:
+            httpGet:
+              path: /healthz
+              port: 6789
+            initialDelaySeconds: 15
+            periodSeconds: 20
+      volumes:
+        - name: runner
+          emptyDir: {}

+ 15 - 0
control_plane/roles/webui_awx/files/awx_postgres_pv.yml

@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+  name: awx-postgres-pv
+  namespace: awx
+  labels:
+    type: local
+spec:
+  storageClassName: nfs-client
+  capacity:
+    storage: 10Gi
+  accessModes:
+    - ReadWriteOnce
+  hostPath:
+    path: "/var/nfs_awx"

+ 29 - 0
control_plane/roles/webui_awx/files/awx_projects_pv.yml

@@ -0,0 +1,29 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+  name: awx-projects-pv
+  namespace: awx
+  labels:
+    type: local
+spec:
+  storageClassName: manual
+  capacity:
+    storage: 10Gi
+  accessModes:
+    - ReadWriteOnce
+  hostPath:
+    path: "/etc"
+
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: awx-pv-claim
+  namespace: awx
+spec:
+  storageClassName: manual
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 3Gi

+ 5 - 0
control_plane/roles/webui_awx/files/requirements.yml

@@ -0,0 +1,5 @@
+---
+collections:
+  - community.general
+  - dellemc.openmanage
+  - dellemc.os10

+ 118 - 270
control_plane/roles/webui_awx/tasks/awx_configuration.yml

@@ -1,4 +1,4 @@
-# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,272 +13,120 @@
 # limitations under the License.
 ---
 
-# Get Current AWX configuration
-- name: Waiting for 30 seconds for UI components to be accessible
-  wait_for:
-    timeout: 30
-
-- name: Organization list
-  block:
-    - name: Get organization list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        organizations list -f human
-      register: organizations_list
-      changed_when: no
-      no_log: True
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ organizations_list.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-- name: Project list
-  block:
-    - name: Get project list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        projects list -f human
-      register: projects_list
-      changed_when: no
-      no_log: True
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ projects_list.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-- name: Inventory list
-  block:
-    - name: Get inventory list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        inventory list -f human
-      register: inventory_list
-      changed_when: no
-      no_log: True
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ inventory_list.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-- name: Credential list
-  block:
-    - name: Get credentials list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        credentials list -f human
-      register: credentials_list
-      changed_when: no
-      no_log: True
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ credentials_list.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-- name: Template List
-  block:
-    - name: Get template list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        job_templates list -f human
-      register: job_templates_list
-      changed_when: no
-      no_log: True
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ job_templates_list.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-- name: Group names
-  block:
-    - name: If omnia-inventory exists, fetch group names in the inventory
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        groups list --inventory "{{ omnia_inventory_name }}" -f human
-      register: groups_list
-      when: omnia_inventory_name in inventory_list.stdout
-      no_log: True
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ groups_list.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-- name: Schedules list
-  block:
-    - name: Get schedules list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        schedules list -f human
-      register: schedules_list
-      changed_when: no
-      no_log: True
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ schedules_list.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-# Delete Default Configurations
-- name: Delete default configurations
-  block:
-    - name: Delete default organization
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        organizations delete "{{ default_org }}"
-      when: default_org in organizations_list.stdout
-      register: register_error
-      no_log: True
-
-    - name: Delete default job template
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        job_templates delete "{{ default_template }}"
-      when: default_template in job_templates_list.stdout
-      register: register_error
-      no_log: True
-
-    - name: Delete default project
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        projects delete "{{ default_projects }}"
-      when: default_projects in projects_list.stdout
-      register: register_error
-      no_log: True
-
-    - name: Delete default credential
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        credentials delete "{{ default_credentials }}"
-      when: default_credentials in credentials_list.stdout
-      register: register_error
-      no_log: True
-
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ register_error.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
-
-# Create required configuration if not present
-- name: Create required configurations
-  block:
-    - name: Create organisation
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        organizations create --name "{{ organization_name }}"
-      when: organization_name not in organizations_list.stdout
-      register: register_error
-      no_log: True
-
-    - name: Create new project
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        projects create --name "{{ project_name }}" --organization "{{ organization_name }}"
-        --local_path "{{ role_path.split('/')[-4] }}"
-      when: project_name not in projects_list.stdout
-      register: register_error
-      no_log: True
-
-    - name: Create new omnia inventory
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        inventory create --name "{{ omnia_inventory_name }}" --organization "{{ organization_name }}"
-      when: omnia_inventory_name not in inventory_list.stdout
-      register: register_error
-      no_log: True
-
-    - name: Create groups in omnia inventory
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        groups create --name "{{ item }}" --inventory "{{ omnia_inventory_name }}"
-      when: omnia_inventory_name not in inventory_list.stdout or item not in groups_list.stdout
-      register: register_error
-      no_log: True
-      loop: "{{ group_names }}"
-
-    - name: Create credentials for omnia
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        credentials create --name "{{ credential_name }}" --organization "{{ organization_name }}"
-        --credential_type "{{ credential_type }}"
-        --inputs '{"username": "{{ cobbler_username }}", "password": "{{ cobbler_password }}"}'
-      when: credential_name not in credentials_list.stdout
-      register: register_error
-      no_log: True
-
-    - name: DeployOmnia Template
-      block:
-        - name: Create template to deploy omnia
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            job_templates create
-            --name "{{ omnia_template_name }}"
-            --job_type run
-            --inventory "{{ omnia_inventory_name }}"
-            --project "{{ project_name }}"
-            --playbook "{{ omnia_playbook }}"
-            --verbosity "{{ playbooks_verbosity }}"
-            --ask_skip_tags_on_launch true
-          register: register_error
-          no_log: True
-
-        - name: Associate credential
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            job_templates associate "{{ omnia_template_name }}"
-            --credential ""{{ credential_name }}""
-          register: register_error
-          no_log: True
-
-      when: omnia_template_name not in job_templates_list.stdout
-
-    - name: DynamicInventory template
-      block:
-        - name: Create template to fetch dynamic inventory
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            job_templates create
-            --name "{{ inventory_template_name }}"
-            --job_type run
-            --inventory "{{ omnia_inventory_name }}"
-            --project "{{ project_name }}"
-            --playbook "{{ inventory_playbook }}"
-            --verbosity "{{ playbooks_verbosity }}"
-            --use_fact_cache true
-          register: register_error
-          no_log: True
-
-        - name: Associate credential
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            job_templates associate "{{ inventory_template_name }}"
-            --credential ""{{ credential_name }}""
-          register: register_error
-          no_log: True
-
-      when: inventory_template_name not in job_templates_list.stdout
-
-    - name: Schedule dynamic inventory template
-      block:
-        - name: Get unified job template list
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            unified_job_templates list --name "{{ inventory_template_name }}" -f human
-          no_log: True
-          register: unified_job_template_list
-
-        - name: Get job ID
-          set_fact:
-            job_id: "{{ unified_job_template_list.stdout | regex_search('[0-9]+') }}"
-
-        - name: Schedule dynamic inventory job
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            schedules create --name "{{ schedule_name }}"
-            --unified_job_template="{{ job_id }}" --rrule="{{ schedule_rule }}"
-          register: register_error
-          no_log: True
-
-      when: schedule_name not in schedules_list.stdout
-
-  rescue:
-    - name: Message
-      fail:
-        msg: "{{ register_error.stdout | regex_replace(awx_user) | regex_replace(admin_password) }}"
+# Deleting the defaults
+- name: Delete machine credential
+  awx.awx.tower_credential:
+    name: "{{ default_credential }}"
+    credential_type: "{{ default_credential_type }}"
+    state: absent
+    tower_config_file: "~/.tower_cli.cfg"
+
+- name: Delete job template
+  awx.awx.tower_job_template:
+    name: "{{ default_template }}"
+    state: absent
+    tower_config_file: "~/.tower_cli.cfg"
+    
+- name: Delete project
+  awx.awx.tower_project:
+    name: "{{ default_project }}"
+    state: absent
+    tower_config_file: "~/.tower_cli.cfg"
+
+- name: Delete organization
+  awx.awx.tower_organization:
+    name: "{{ default_org }}"
+    state: absent
+    tower_config_file: "~/.tower_cli.cfg"
+
+# Configuration begins
+- name: Create organization
+  awx.awx.tower_organization:
+    name: "{{ awx_organization }}"
+    description: "Name of organization using this product"
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+
+- name: Create awx inventories
+  awx.awx.tower_inventory:
+    name: "{{ item.name }}"
+    description: "{{ item.description }}"
+    organization: "{{ awx_organization }}"
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+  loop: "{{ inventory_names }}"
+  when: item.flag
+
+- name: Add groups to node_inventory
+  awx.awx.tower_group:
+    name: "{{ item.name }}"
+    description: "{{ item.description }}"
+    inventory: "node_inventory"
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+  loop: "{{ group_names }}"
+
+- name: Add project
+  awx.awx.tower_project:
+    name: "{{ project_name }}"
+    description: "{{ project_description }}"
+    organization: "{{ awx_organization }}"
+    scm_type: manual
+    local_path: "{{ role_path.split('/')[-4] }}"
+    default_environment: "custom-awx-ee"
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+
+- name: Add awx credentials
+  awx.awx.tower_credential:
+    name: "{{ item.name }}"
+    organization: "{{ awx_organization }}"
+    credential_type: "{{ item.type }}"
+    inputs:
+      username: "{{ item.username }}"
+      password: "{{ item.password }}"
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+  loop: "{{ credential_details }}"
+  changed_when: true
+  when: item.flag
+
+- name: Create awx job templates
+  awx.awx.tower_job_template:
+    name: "{{ item.name }}"
+    job_type: "run"
+    organization: "{{ awx_organization }}"
+    inventory: "{{ item.inventory }}"
+    project: "{{ project_name }}"
+    playbook: "{{ item.playbook }}"
+    credentials:
+      - "{{ item.credential }}"
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+  loop: "{{ job_template_details }}"
+  when: item.flag
+
+- name: Create deploy_omnia_template
+  awx.awx.tower_job_template:
+    name: "{{ item.name }}"
+    job_type: "run"
+    organization: "{{ awx_organization }}"
+    inventory: "{{ item.inventory }}"
+    project: "{{ project_name }}"
+    playbook: "{{ item.playbook }}"
+    credentials:
+      - "{{ item.credential }}"
+    ask_skip_tags_on_launch: true
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+  loop: "{{ deploy_omnia_details }}"
+
+- name: Build a schedule for idrac job template
+  awx.awx.tower_schedule:
+    name: "{{ item.name }}"
+    unified_job_template: "{{ item.template }}"
+    rrule: "{{ schedule_rule }}"
+    state: present
+    tower_config_file: "~/.tower_cli.cfg"
+  register: result
+  loop: "{{ scheduled_templates}}"

+ 71 - 0
control_plane/roles/webui_awx/tasks/configure_settings.yml

@@ -0,0 +1,71 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+# Get Current AWX configuration
+
+- name: Get awx-service Cluster-IP
+  command: "kubectl get svc awx-service -n {{ awx_namespace }} -o jsonpath='{.spec.clusterIP}'"
+  register: awx_cluster_ip
+  changed_when: false
+
+- name: Get AWX admin password
+  shell: "kubectl get secret awx-admin-password -n {{ awx_namespace }} -o jsonpath='{.data.password}' | base64 --decode"
+  register: awx_admin_password
+  changed_when: false
+
+- name: Check if config file exists
+  stat:
+    path: "~/.tower_cli.cfg"
+  register: config_file_status
+
+- name: Create config file
+  copy:
+    dest:  "~/.tower_cli.cfg"
+    content: |
+      [general]
+      host: http://{{ awx_cluster_ip.stdout }}
+      username: admin
+      password: {{ awx_admin_password.stdout }}
+      verify_ssl: false
+      use_token: false
+    owner: root
+    mode: "{{ file_perm }}"
+
+- name: Stop and disable firewalld
+  service:
+    name: firewalld
+    state: stopped
+    enabled: no
+
+- name: Waiting for the AWX UI to be up
+  uri:
+    url: "http://{{ awx_cluster_ip.stdout }}"
+    status_code: "{{ return_status }}"
+  register: display
+  until: display.status == 200
+  retries: 20
+  delay: 15
+  changed_when: false
+
+- name: Waiting for the AWX UI to be in running state
+  uri:
+    url: "http://{{ awx_cluster_ip.stdout }}"
+    status_code: "{{ return_status }}"
+    return_content: true
+  register: display
+  until: awx_ui_msg not in display.content
+  retries: 20
+  delay: 15
+  changed_when: false

+ 77 - 45
control_plane/roles/webui_awx/tasks/install_awx.yml

@@ -1,4 +1,4 @@
-# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,50 +15,82 @@
 
 # Tasks for installing AWX
 
-- name: Change inventory file
+- name: Get all namespaces
+  command: kubectl get ns
+  changed_when: false
+  register: namespaces
+
+- name: Create namespace
+  command: "kubectl create namespace {{ awx_namespace }}"
+  changed_when: true
+  when: "'awx' not in namespaces.stdout"
+
+- name: Get K8s pods
+  command: "kubectl get pods -n {{ awx_namespace }}"
+  changed_when: false
+  register: k8s_pods
+
+- name: Deploy awx-operator
+  command: "kubectl apply -f {{ awx_operator_yml_file_path }}"
+  changed_when: true
+  when: '"awx-operator" not in k8s_pods.stdout'
+
+- name: Get K8s persistent volumes
+  command: "kubectl get pv -n {{ awx_namespace }}"
+  changed_when: false
+  register: k8s_pvs
+
+- name: Configure host volume as playbooks directory path
   replace:
-    path: "{{ awx_inventory_path }}"
-    regexp: "{{ item.regexp }}"
-    replace: "{{ item.replace }}"
-  loop:
-    - { name: Project data directory, regexp: "{{ project_data_dir_old }}" , replace: "{{ project_data_dir_new }}" }
-    - { name: Alternate DNS Servers, regexp: "{{ awx_alternate_dns_servers_old }}", replace: "{{ awx_alternate_dns_servers_new }}" }
-    - { name: Credentials, regexp: "{{ admin_password_old }}", replace: "{{ admin_password_new }}"}
-  loop_control:
-    label: "{{ item.name }}"
-  tags: install
-
-- name: Ensure port is 8081
-  lineinfile:
-    path: "{{ awx_inventory_path }}"
-    regexp: "{{ port_old }}"
-    line: "{{ port_new }}"
+    path: "{{ awx_pv_yml_file_path }}"
+    regexp: 'path: "/etc"'
+    replace: 'path: "{{ playbook_dir | dirname | dirname }}"'
+  when: "'awx-projects-pv' not in k8s_pvs.stdout"
+
+- name: Create persistent volume and volumeclaim for projects
+  command: "kubectl apply -f {{ awx_pv_yml_file_path }}"
+  changed_when: true
+  when: "'awx-projects-pv' not in k8s_pvs.stdout"
+
+- name: Create persistent volume for postgres
+  command: "kubectl apply -f {{ awx_postgres_pv_file_path }}"
+  changed_when: true
+  when: "'awx-postgres-pv' not in k8s_pvs.stdout"
+
+- name: Get the docker images
+  command: buildah images
+  changed_when: false
+  register: docker_images
+
+- name: Build the custom-awx-ee image from the docker file
+  command: "buildah bud -t custom-awx-ee {{ awx_ee_docker_file }}"
+  changed_when: false
+  when: "'custom-awx-ee' not in docker_images.stdout"
+
+- name: Waiting for awx-operator deployment to be up and running
+  shell: "kubectl wait --for=condition=available deployment/awx-operator -n {{ awx_namespace }} --timeout=600s"
+  changed_when: false
+
+- name: Deploy awx
+  command: "kubectl apply -f {{ awx_yml_file_path }}"
+  changed_when: true
+  when: not k8s_pods.stdout | regex_search('awx-([A-Za-z0-9]{10})-([A-Za-z0-9]{5})')
+
+- name: Install awxkit using pip3
+  pip:
+    name: awxkit
     state: present
 
-- name: Create pgdocker directory
-  file:
-    path: "{{ pgdocker_dir_path }}"
-    state: directory
-    mode: 0775
-  tags: install
-
-- name: Install AWX
-  block:
-    - name: Run AWX install.yml file
-      command: ansible-playbook -i inventory install.yml --extra-vars "admin_password={{ admin_password }}"
-      args:
-        chdir: "{{ awx_installer_path }}"
-      register: awx_installation
-      no_log: True
-
-  rescue:
-    - name: Check AWX status on machine
-      include_tasks: check_awx_status.yml
-
-    - name: Fail if container are not running
-      fail:
-        msg: "AWX installation failed with error msg:
-        {{ awx_installation.stdout | regex_replace(admin_password) }}."
-      when: not awx_status
-
-  tags: install
+- name: Install awx collection
+  command: "ansible-galaxy collection install awx.awx:{{ awx_version }}"
+  changed_when: true
+  register: installation_status
+
+- name: Wait for awx pods to get created
+  wait_for:
+    timeout: "{{ awx_wait_time }}"
+  when: not k8s_pods.stdout | regex_search('awx-([A-Za-z0-9]{10})-([A-Za-z0-9]{5})')
+
+- name: Waiting for awx deployment to be up and running
+  shell: "kubectl wait --for=condition=available deployment/awx -n {{ awx_namespace }} --timeout=1200s"
+  changed_when: false

+ 6 - 42
control_plane/roles/webui_awx/tasks/main.yml

@@ -1,4 +1,4 @@
-# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,63 +14,27 @@
 ---
 
 # Tasks for Deploying AWX on the system
-- name: Check AWX status on machine
-  include_tasks: check_awx_status.yml
-  tags: install
-
-- name: Include control_plane_common variables
-  include_vars: ../../control_plane_common/vars/main.yml
-  tags: install
 
 - name: Internet validation
   include_tasks: ../../control_plane_common/tasks/internet_validation.yml
-  when: not awx_status
-  tags: install
-
-- name: Clone AWX repo
-  include_tasks: clone_awx.yml
-  when: not awx_status
-  tags: install
-
-- name: Modify firewall config
-  include_tasks: firewall_settings.yml
-  when: not awx_status
   tags: install
 
 - name: Install AWX
   include_tasks: install_awx.yml
-  when: not awx_status
-  tags: install
-
-- name: Status message
-  block:
-    - debug:
-        msg: "{{ message_skipped }}"
-        verbosity: 2
-      when: awx_status
-    - debug:
-        msg: "{{ message_installed }}"
-        verbosity: 2
-      when: not awx_status
   tags: install
 
 - name: Internet validation
   include_tasks: ../../control_plane_common/tasks/internet_validation.yml
   tags: install
 
-- name: Install AWX-CLI
-  include_tasks: install_awx_cli.yml
+- name: Configure settings
+  include_tasks: configure_settings.yml
   tags: install
 
-- name: Check if AWX-UI is accessible
-  include_tasks: ui_accessibility.yml
+- name: Internet validation
+  include_tasks: ../../control_plane_common/tasks/internet_validation.yml
   tags: install
 
 - name: Configure AWX
-  block:
-    - include_tasks: awx_configuration.yml
-  rescue:
-    - name: Display msg
-      debug:
-        msg: "{{ conf_fail_msg }}"
+  include_tasks: awx_configuration.yml
   tags: install

+ 50 - 46
control_plane/roles/webui_awx/vars/main.yml

@@ -1,4 +1,4 @@
-# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,58 +12,62 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ---
-
 # vars file for webui_awx
 
-# Usage: clone_awx.yml
-awx_git_repo: "https://github.com/ansible/awx.git"
-docker_volume: "/var/lib/docker/volumes/{{ docker_volume_name }}"
-awx_repo_path: "{{ docker_volume }}/awx/"
-awx_installer_path: "{{ awx_repo_path }}/installer/"
-
 # Usage: install_awx.yml
-awx_inventory_path: "{{ awx_repo_path }}/installer/inventory"
-pgdocker_dir_path: /var/lib/pgdocker
-project_data_dir_old: "#project_data_dir=/var/lib/awx/projects"
-project_data_dir_new: "project_data_dir= {{ role_path + '/../../../..' }} "
-awx_alternate_dns_servers_old: '#awx_alternate_dns_servers="10.1.2.3,10.2.3.4"'
-awx_alternate_dns_servers_new: 'awx_alternate_dns_servers="8.8.8.8,8.8.4.4"'
-admin_password_old: "admin_password=password"
-admin_password_new: "#admin_password=password"
-port_old: "host_port=80"
-port_new: "host_port=8081"
+awx_namespace: awx
+awx_pv_yml_file_path: "{{ role_path }}/files/awx_projects_pv.yml"
+awx_postgres_pv_file_path: "{{ role_path }}/files/awx_postgres_pv.yml"
+awx_pvc_yml_file_path: "{{ role_path }}/files/awx_projects_pvclaim.yml"
+awx_operator_yml_file_path: "{{ role_path }}/files/awx_operator.yml"
+awx_ee_docker_file: "{{ role_path }}/files/awx_ee.yml"
+awx_yml_file_path: "{{ role_path }}/files/awx.yml"
+postgres_storage_class: nfs-client
+projects_existing_claim: awx-pv-claim
+awx_version: 19.1.0
+file_perm: 644
+awx_wait_time: 90
 
-# Usage: main.yml
-message_skipped: "Installation Skipped: AWX instance is already running on your system"
-message_installed: "Installation Successful"
-awx_ip: http://localhost:8081
+# Usage: configure_settings.yml
+awx_ui_msg: "AWX Upgrading"
 return_status: 200
-awx_ui_msg: "Password Dialog"
-conf_fail_msg: "AWX configuration failed at the last executed task."
-
-# Usage: install_awx_cli.yml
-awx_cli_repo: "https://releases.ansible.com/ansible-tower/cli/ansible-tower-cli-centos7.repo"
-awx_cli_repo_path: "/etc/yum.repos.d/ansible-tower-cli-centos7.repo"
 
 # Usage: awx_configuration.yml
-awx_user: admin         #Don't change it. It is set as admin while installing AWX
 default_org: Default
 default_template: 'Demo Job Template'
-default_projects: 'Demo Project'
-default_credentials: 'Demo Credential'
-organization_name: DellEMC
-project_name: omnia
-omnia_inventory_name: omnia_inventory
+default_project: 'Demo Project'
+default_credential: 'Demo Credential'
+default_credential_type: Machine
+organization_name: 'DellEMC'
+project_name: 'omnia'
+project_description: "Directory which contains configuration playbooks"
+inventory_names:
+  - { name: idrac_inventory, description: "Inventory to store IPs of idrac servers", flag: true }
+  - { name: ethernet_inventory, description: "Inventory to store IPs of ethernet switches", flag: "{{ ethernet_switch_support }}" }
+  - { name: infiniband_inventory, description: "Inventory to store IPs of infiniband switches", flag: "{{ ib_switch_support }}" }
+  - { name: powervault_me4_inventory, description: "Inventory to store IPs of ME4 servers", flag: "{{ powervault_support }}" }
+  - { name: node_inventory, description: "Inventory to store host IPs of servers", flag: true }
 group_names:
-  - manager
-  - compute
-credential_name: omnia_credential
-credential_type: Machine
-cobbler_username: root
-omnia_template_name: DeployOmnia
-omnia_playbook: omnia.yml
-inventory_template_name: DynamicInventory
-inventory_playbook: control_plane/collect_node_info.yml
-playbooks_verbosity: 0
-schedule_name: DynamicInventorySchedule
-schedule_rule: "DTSTART:20201201T000000Z RRULE:FREQ=MINUTELY;INTERVAL=10"
+  - { name: manager, description: "Group to store IP of head node" }
+  - { name: compute, description: "Group to store IPs of compute nodes" }
+  - { name: login, description: "Group to store IP of login node" }
+  - { name: nfs, description: "Group to store IP of NFS node" }
+credential_details:
+  - { name: idrac_credential, type: Network, username: "{{ idrac_username }}", password: "{{ idrac_password }}", flag: true }
+  - { name: ethernet_credential, type: Machine, username: "{{ ethernet_switch_username }}", password: "{{ ethernet_switch_password }}", flag: "{{ ethernet_switch_support }}" }
+  - { name: infiniband_credential, type: Network, username: "{{ ib_username }}", password: "{{ ib_password }}", flag: "{{ ib_switch_support }}" }
+  - { name: powervault_me4_credential, type: Network, username: "{{ powervault_me4_username }}", password: "{{ powervault_me4_password }}", flag: "{{ powervault_support }}" }
+  - { name: node_credential, type: Machine, username: root, password: "{{ provision_password }}", flag: true }
+job_template_details:
+  - { name: idrac_template, inventory: idrac_inventory, playbook: control_plane/idrac.yml, credential: idrac_credential, flag: true }
+  - { name: ethernet_template, inventory: ethernet_inventory, playbook: control_plane/ethernet.yml, credential: ethernet_credential, flag: "{{ ethernet_switch_support }}" }
+  - { name: infiniband_template, inventory: infiniband_inventory, playbook: control_plane/infiniband.yml, credential: infiniband_credential, flag: "{{ ib_switch_support }}" }
+  - { name: powervault_me4_template, inventory: powervault_me4_inventory, playbook: control_plane/powervault_me4.yml, credential: powervault_me4_credential, flag: "{{ powervault_support }}" }
+  - { name: node_inventory_job, inventory: node_inventory, playbook: control_plane/collect_node_info.yml, credential: node_credential, flag: true }
+  - { name: device_inventory_job, inventory: node_inventory, playbook: control_plane/collect_device_info.yml, credential: node_credential, flag: true }
+deploy_omnia_details:
+  - { name: deploy_omnia_template, inventory: node_inventory, playbook: omnia.yml, credential: node_credential }
+schedule_rule: "DTSTART:20210608T120000Z RRULE:FREQ=MINUTELY;INTERVAL=10"
+scheduled_templates:
+  - { name: NodeInventorySchedule, template: node_inventory_job }
+  - { name: DeviceInventorySchedule, template: device_inventory_job }

+ 21 - 0
control_plane/tools/idrac_secure_boot.yml

@@ -0,0 +1,21 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Enable/Disable secure boot in idrac servers
+  hosts: all
+  connection: local
+  gather_facts: false
+  roles:
+    - idrac_secure_boot

+ 21 - 0
control_plane/tools/idrac_system_lockdown.yml

@@ -0,0 +1,21 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Enable/Disable system lockdown in idrac servers
+  hosts: all
+  connection: local
+  gather_facts: false
+  roles:
+    - idrac_system_lockdown

+ 41 - 0
control_plane/tools/roles/idrac_secure_boot/tasks/configure_secure_boot.yml

@@ -0,0 +1,41 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Assert uefi_secure_boot value
+  assert:
+    that:
+      - uefi_secure_boot | length > 1
+      - uefi_secure_boot == "enabled" or uefi_secure_boot == "disabled"
+    success_msg: "{{ secure_boot_success_msg }}"
+    fail_msg: "{{ secure_boot_fail_msg }}"
+  run_once: true
+
+- name: Enable secure boot
+  dellemc.openmanage.idrac_bios:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password:  "{{ idrac_password }}"
+    attributes:
+      SecureBoot: "Enabled"
+  when: uefi_secure_boot == "enabled"
+
+- name: Disable secure boot
+  dellemc.openmanage.idrac_bios:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password:  "{{ idrac_password }}"
+    attributes:
+      SecureBoot: "Disabled"
+  when: uefi_secure_boot == "disabled"

+ 20 - 0
control_plane/tools/roles/idrac_secure_boot/tasks/main.yml

@@ -0,0 +1,20 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Check prerequisites
+  include_tasks: ./../idrac_system_lockdown/tasks/check_prerequisites.yml
+
+- name: Configure secure boot
+  include_tasks: configure_secure_boot.yml

+ 20 - 0
control_plane/tools/roles/idrac_secure_boot/vars/main.yml

@@ -0,0 +1,20 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+# vars file for idrac_secure_boot role
+
+# Usage: configure_secure_boot.yml
+secure_boot_success_msg: "uefi_secure_boot validated"
+secure_boot_fail_msg: "Failed. uefi_secure_boot accepts only enabled or disabled in idrac_vars.yml"

+ 56 - 0
control_plane/tools/roles/idrac_system_lockdown/tasks/check_prerequisites.yml

@@ -0,0 +1,56 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Include provision_idrac vars
+  include_vars: "{{ playbook_dir }}/../roles/provision_idrac/vars/main.yml"
+  run_once: true
+
+- name: Include idrac_vars.yml
+  include_vars: "{{ playbook_dir }}/../{{ idrac_input_filename }}"
+  run_once: true
+
+- name: Check hostname
+  command: hostname
+  changed_when: false
+  register: hostname
+  run_once: true
+
+- name: Set idrac credentials
+  set_fact:
+    idrac_username: "{{ lookup('env','ANSIBLE_NET_USERNAME') }}"
+    idrac_password: "{{ lookup('env','ANSIBLE_NET_PASSWORD') }}"
+  no_log: true
+  when: '"awx-" in hostname.stdout'
+  run_once: true
+
+- name: Fetch idrac credentials
+  include_tasks: "{{ playbook_dir }}/../roles/provision_idrac/tasks/fetch_idrac_credentials.yml"
+  vars:
+    login_input_filename: "{{ playbook_dir }}/../input_params/login_vars.yml"
+    login_vault_filename: "{{ playbook_dir }}/../input_params/.login_vault_key"
+  when: '"awx-" not in hostname.stdout'
+
+- name: Show status of the Lifecycle Controller
+  dellemc.openmanage.idrac_lifecycle_controller_status_info:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+  register: lc_check_status
+
+- name: LC not available
+  fail:
+    msg: "{{ lc_check_fail_msg }}"
+  when: not lc_check_status.lc_status_info.LCReady
+  register: lc_fail

+ 41 - 0
control_plane/tools/roles/idrac_system_lockdown/tasks/configure_system_lockdown.yml

@@ -0,0 +1,41 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Assert system_lockdown value
+  assert:
+    that:
+      - system_lockdown | length > 1
+      - system_lockdown == "enabled" or system_lockdown == "disabled"
+    success_msg: "{{ system_lockdown_success_msg }}"
+    fail_msg: "{{ system_lockdown_fail_msg }}"
+  run_once: true
+
+- name: Enable system lockdown
+  dellemc.openmanage.dellemc_system_lockdown_mode:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+    share_name: "{{ playbook_dir }}"
+    lockdown_mode: "Enabled"
+  when: system_lockdown == "enabled"
+
+- name: Disable system lockdown
+  dellemc.openmanage.dellemc_system_lockdown_mode:
+    idrac_ip: "{{ inventory_hostname }}"
+    idrac_user: "{{ idrac_username }}"
+    idrac_password: "{{ idrac_password }}"
+    share_name: "{{ playbook_dir }}"
+    lockdown_mode: "Disabled"
+  when: system_lockdown == "disabled"

+ 20 - 0
control_plane/tools/roles/idrac_system_lockdown/tasks/main.yml

@@ -0,0 +1,20 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Check prerequisites
+  include_tasks: check_prerequisites.yml
+
+- name: Configure system lockdown 
+  include_tasks: configure_system_lockdown.yml

+ 20 - 0
control_plane/tools/roles/idrac_system_lockdown/vars/main.yml

@@ -0,0 +1,20 @@
+# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+# vars file for idrac_system_lockdown role
+
+# Usage: configure_system_lockdown.yml
+system_lockdown_success_msg: "system_lockdown validated"
+system_lockdown_fail_msg: "Failed. system_lockdown accepts only enabled or disabled in idrac_vars.yml"