Browse Source

Merge branch 'devel' into patch-2

John Lockman 3 years ago
parent
commit
08a4c97154
100 changed files with 26487 additions and 947 deletions
  1. 54 33
      .all-contributorsrc
  2. 2 2
      .github/workflows/ansible-lint.yml
  3. 12 10
      README.md
  4. 39 12
      control_plane/control_plane.yml
  5. 15 5
      control_plane/input_params/base_vars.yml
  6. 26 2
      control_plane/input_params/login_vars.yml
  7. 12 12
      control_plane/input_params/powervault_me4_vars.yml
  8. 23 0
      control_plane/input_params/security_vars.yml
  9. 1 1
      control_plane/roles/collect_node_info/vars/main.yml
  10. 1 1
      control_plane/roles/control_plane_repo/files/poweredge_models.txt
  11. 1 5
      control_plane/roles/control_plane_common/tasks/count_component_roles.yml
  12. 41 311
      control_plane/roles/control_plane_common/tasks/fetch_base_inputs.yml
  13. 45 0
      control_plane/roles/control_plane_common/tasks/fetch_security_inputs.yml
  14. 10 10
      control_plane/roles/control_plane_common/tasks/fetch_sm_inputs.yml
  15. 1 2
      control_plane/roles/control_plane_common/tasks/internet_validation.yml
  16. 21 11
      control_plane/roles/control_plane_common/tasks/main.yml
  17. 12 6
      control_plane/roles/control_plane_common/tasks/package_installation.yml
  18. 65 25
      control_plane/roles/control_plane_common/tasks/pre_requisite.yml
  19. 1 11
      control_plane/roles/control_plane_common/tasks/validate_device_mapping_file.yml
  20. 1 21
      control_plane/roles/control_plane_common/tasks/validate_host_mapping_file.yml
  21. 45 0
      control_plane/roles/control_plane_common/tasks/validate_idrac_vars.yml
  22. 299 0
      control_plane/roles/control_plane_common/tasks/validate_nic_vars.yml
  23. 81 0
      control_plane/roles/control_plane_common/tasks/validate_provision_vars.yml
  24. 77 1
      control_plane/roles/control_plane_common/tasks/password_config.yml
  25. 27 3
      control_plane/roles/control_plane_common/tasks/verify_omnia_params.yml
  26. 51 3
      control_plane/roles/control_plane_common/vars/main.yml
  27. 84 0
      control_plane/roles/control_plane_customiso/files/temp_leap15.xml
  28. 40 9
      control_plane/roles/control_plane_customiso/tasks/check_prerequisites.yml
  29. 0 80
      control_plane/roles/control_plane_customiso/tasks/create_unattended_iso.yml
  30. 39 0
      control_plane/roles/control_plane_customiso/tasks/create_unattended_iso_centos.yml
  31. 39 0
      control_plane/roles/control_plane_customiso/tasks/create_unattended_iso_leap.yml
  32. 44 0
      control_plane/roles/control_plane_customiso/tasks/create_unattended_iso_rocky.yml
  33. 175 113
      control_plane/roles/control_plane_customiso/tasks/edit_iso_config.yml
  34. 12 3
      control_plane/roles/control_plane_customiso/tasks/main.yml
  35. 22 10
      control_plane/roles/control_plane_customiso/vars/main.yml
  36. 9 26
      control_plane/roles/control_plane_device/files/Dockerfile
  37. 2 0
      control_plane/roles/control_plane_device/files/cron_inv
  38. 12 3
      control_plane/roles/control_plane_device/files/inventory_creation.yml
  39. 6 3
      control_plane/roles/control_plane_device/files/k8s_mngmnt_network.yml
  40. 19 56
      control_plane/roles/control_plane_device/files/mngmnt_container_configure.yml
  41. 0 20
      control_plane/roles/control_plane_device/files/tftp
  42. 2 2
      control_plane/roles/control_plane_device/tasks/configure_mngmnt_network_container.yml
  43. 7 19
      control_plane/roles/control_plane_ib/files/Dockerfile
  44. 5 5
      control_plane/roles/control_plane_ib/files/infiniband_container_configure.yml
  45. 6 3
      control_plane/roles/control_plane_ib/files/k8s_infiniband.yml
  46. 4 5
      control_plane/roles/control_plane_k8s/tasks/k8s_init.yml
  47. 4 5
      control_plane/roles/control_plane_k8s/tasks/k8s_installation.yml
  48. 187 0
      control_plane/roles/control_plane_k8s/tasks/k8s_installation_leap.yml
  49. 10 3
      control_plane/roles/control_plane_k8s/tasks/main.yml
  50. 22 1
      control_plane/roles/control_plane_k8s/vars/main.yml
  51. 1363 0
      control_plane/roles/control_plane_monitoring/files/CoreDNS.json
  52. 3 0
      control_plane/roles/control_plane_monitoring/files/Dockerfile_promtail
  53. 1527 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_API_server.json
  54. 2266 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Cluster.json
  55. 2039 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Namespace_Pods.json
  56. 918 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Node_Pods.json
  57. 1638 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Pod.json
  58. 1850 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Workload.json
  59. 2071 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Kubelet.json
  60. 1615 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Cluster.json
  61. 1297 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Namespace_Pods.json
  62. 1492 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Namespace_Workload.json
  63. 1085 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Pod.json
  64. 1226 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Workload.json
  65. 963 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_Scheduler.json
  66. 820 0
      control_plane/roles/control_plane_monitoring/files/Kubernetes_StatefulSets.json
  67. 1163 0
      control_plane/roles/control_plane_monitoring/files/Prometheus_Overview.json
  68. 135 0
      control_plane/roles/control_plane_monitoring/files/loki_dashboard.json
  69. 138 0
      control_plane/roles/control_plane_monitoring/files/promtail_config.yml
  70. 59 0
      control_plane/roles/control_plane_monitoring/tasks/configure_k8s_prom_grafana.yml
  71. 49 0
      control_plane/roles/control_plane_monitoring/tasks/configure_loki_grafana.yml
  72. 63 0
      control_plane/roles/control_plane_monitoring/tasks/install_k8s_prom_stack.yml
  73. 63 0
      control_plane/roles/control_plane_monitoring/tasks/k8s_loki_pod.yml
  74. 33 0
      control_plane/roles/control_plane_monitoring/tasks/loki_service.yml
  75. 32 0
      control_plane/roles/control_plane_monitoring/tasks/main.yml
  76. 27 0
      control_plane/roles/control_plane_monitoring/tasks/promtail_image.yml
  77. 56 0
      control_plane/roles/control_plane_monitoring/vars/main.yml
  78. 1 1
      control_plane/roles/control_plane_repo/tasks/download_fmw_updates.yml
  79. 1 1
      control_plane/roles/control_plane_repo/tasks/install_dsu.yml
  80. 8 11
      control_plane/roles/control_plane_repo/tasks/main.yml
  81. 3 10
      control_plane/roles/control_plane_repo/vars/main.yml
  82. 21 0
      control_plane/roles/control_plane_security/tasks/enable_dnf_module.yml
  83. 60 0
      control_plane/roles/control_plane_security/tasks/firewall_settings.yml
  84. 61 0
      control_plane/roles/control_plane_security/tasks/install_ipa_server.yml
  85. 41 0
      control_plane/roles/control_plane_security/tasks/install_packages.yml
  86. 39 0
      control_plane/roles/control_plane_security/tasks/main.yml
  87. 23 0
      control_plane/roles/control_plane_security/tasks/update_package.yml
  88. 50 0
      control_plane/roles/control_plane_security/vars/main.yml
  89. 64 24
      control_plane/roles/deploy_job_templates/tasks/group_inventory.yml
  90. 0 1
      control_plane/roles/deploy_job_templates/tasks/main.yml
  91. 1 0
      control_plane/roles/deploy_job_templates/vars/main.yml
  92. 71 0
      control_plane/roles/provision_cobbler/files/Dockerfile_leap
  93. 8 8
      control_plane/roles/provision_cobbler/files/Dockerfile
  94. 140 0
      control_plane/roles/provision_cobbler/files/cobbler_configurations_leap.yml
  95. 11 35
      control_plane/roles/provision_cobbler/files/cobbler_configurations.yml
  96. 8 2
      control_plane/roles/provision_cobbler/files/inventory_creation.yml
  97. 1 1
      control_plane/roles/provision_cobbler/files/k8s_cobbler.yml
  98. 85 0
      control_plane/roles/provision_cobbler/files/multi_cluster_provisioning.yml
  99. 86 0
      control_plane/roles/provision_cobbler/files/temp_leap15.xml
  100. 0 0
      control_plane/roles/provision_cobbler/files/tftp.yml

+ 54 - 33
.all-contributorsrc

@@ -42,27 +42,39 @@
       ]
     },
     {
+      "login": "sujit-jadhav",
+      "name": "Sujit Jadhav",
+      "avatar_url": "https://avatars.githubusercontent.com/u/73123831?v=4",
+      "profile": "https://github.com/sujit-jadhav",
+      "contributions": [
+        "ideas",
+        "doc",
+        "code",
+        "review",
+        "maintenance",
+        "projectManagement",
+        "mentoring"
+      ]
+    },
+    {
       "login": "DeepikaKrishnaiah",
-      "name": "DeepikaKrishnaiah",
+      "name": "Deepika K",
       "avatar_url": "https://avatars.githubusercontent.com/u/73213880?v=4",
       "profile": "https://github.com/DeepikaKrishnaiah",
       "contributions": [
         "code",
         "test",
-        "bug"
+        "bug",
+        "security"
       ]
     },
     {
-      "login": "sujit-jadhav",
-      "name": "sujit-jadhav",
-      "avatar_url": "https://avatars.githubusercontent.com/u/73123831?v=4",
-      "profile": "https://github.com/sujit-jadhav",
+      "login": "sakshiarora13",
+      "name": "Sakshi Arora",
+      "avatar_url": "https://avatars.githubusercontent.com/u/73195862?v=4",
+      "profile": "https://github.com/sakshiarora13",
       "contributions": [
-        "ideas",
-        "doc",
-        "code",
-        "review",
-        "maintenance"
+        "code"
       ]
     },
     {
@@ -106,15 +118,6 @@
       ]
     },
     {
-      "login": "sakshiarora13",
-      "name": "sakshiarora13",
-      "avatar_url": "https://avatars.githubusercontent.com/u/73195862?v=4",
-      "profile": "https://github.com/sakshiarora13",
-      "contributions": [
-        "code"
-      ]
-    },
-    {
       "login": "avinashvishwanath",
       "name": "avinashvishwanath",
       "avatar_url": "https://avatars.githubusercontent.com/u/77823538?v=4",
@@ -146,6 +149,24 @@
       ]
     },
     {
+      "login": "cgoveas",
+      "name": "Cassey Goveas",
+      "avatar_url": "https://avatars.githubusercontent.com/u/88071888?v=4",
+      "profile": "https://github.com/cgoveas",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "abhishek-sa1",
+      "name": "Abhishek SA",
+      "avatar_url": "https://avatars.githubusercontent.com/u/94038029?v=4",
+      "profile": "https://github.com/abhishek-sa1",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
       "login": "Franklin-Johnson",
       "name": "Franklin-Johnson",
       "avatar_url": "https://avatars.githubusercontent.com/u/84760103?v=4",
@@ -185,15 +206,6 @@
       ]
     },
     {
-      "login": "cgoveas",
-      "name": "Cassey Goveas",
-      "avatar_url": "https://avatars.githubusercontent.com/u/88071888?v=4",
-      "profile": "https://github.com/cgoveas",
-      "contributions": [
-        "doc"
-      ]
-    },
-    {
       "login": "asu-wdizon",
       "name": "William Dizon",
       "avatar_url": "https://avatars.githubusercontent.com/u/81772355?v=4",
@@ -315,10 +327,19 @@
       ]
     },
     {
-      "login": "abhishek-sa1",
-      "name": "abhishek-sa1",
-      "avatar_url": "https://avatars.githubusercontent.com/u/94038029?v=4",
-      "profile": "https://github.com/abhishek-sa1",
+      "login": "Lakshmi-Patneedi",
+      "name": "Lakshmi-Patneedi",
+      "avatar_url": "https://avatars.githubusercontent.com/u/94051091?v=4",
+      "profile": "https://github.com/Lakshmi-Patneedi",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "Artlands",
+      "name": "Jie Li",
+      "avatar_url": "https://avatars.githubusercontent.com/u/31781106?v=4",
+      "profile": "https://github.com/Artlands",
       "contributions": [
         "code"
       ]

+ 2 - 2
.github/workflows/ansible-lint.yml

@@ -38,8 +38,8 @@ jobs:
         # Arguments to override a package and its version to be set explicitly.
         # Must follow the example syntax.
         override-deps: |
-          ansible==2.10
-          ansible-lint==5.1.2
+          ansible==4.10
+          ansible-lint==5.3.2
         # [optional]
         # Arguments to be passed to the ansible-lint
 

File diff suppressed because it is too large
+ 12 - 10
README.md


+ 39 - 12
control_plane/control_plane.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,17 +13,44 @@
 #  limitations under the License.
 ---
 
-- name: Executing omnia roles
+- name: Executing control_plane roles
   hosts: localhost
   connection: local
   roles:
-    - control_plane_common
-    - control_plane_k8s
-    - control_plane_device
-    - provision_cobbler
-    - webui_awx
-    - control_plane_ib
-    - control_plane_sm
-    - control_plane_customiso
-    - control_plane_repo
-    - deploy_job_templates
+    - role: control_plane_common
+
+    - role: control_plane_k8s
+      tags: init
+
+    - role: control_plane_device
+      tags: network-device
+
+    - role: provision_cobbler
+      tags: pxe
+
+    - role: webui_awx
+      tags: awx
+
+    - role: webui_grafana
+      tags: monitoring
+
+    - role: control_plane_ib
+      tags: network-ib
+
+    - role: control_plane_sm
+      tags: network-ib
+
+    - role: control_plane_customiso
+      tags: idrac
+
+    - role: control_plane_repo
+      tags: firmware-repo
+
+    - role: control_plane_security
+      tags: security
+
+    - role: control_plane_monitoring
+      tags: monitoring
+
+    - role: deploy_job_templates
+      tags: templates

+ 15 - 5
control_plane/input_params/base_vars.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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.
@@ -37,6 +37,12 @@ ib_switch_support: true
 # If powervault configuration is needed, set this to "true"
 powervault_support: false
 
+# This variable is used to enable security features on MS
+# Accepted values: "true" or "false"
+# Default value: "true"
+# If security features are not needed, set this to "false"
+enable_security_support: true
+
 # The nic/ethernet card that will be connected to the public internet.
 # Default value: eno2
 public_nic: "eno2"
@@ -63,6 +69,10 @@ snmp_community_name: "public"
 # Default value: “DellEMC”
 awx_organization: "DellEMC"
 
+### Usage: webui_grafana ###
+# At this location grafana persistent volume will be created.
+mount_location: /mnt/omnia/
+
 ### Usage: provision_cobbler, provision_idrac ###
 
 # This variable is used to set node provisioning method
@@ -80,16 +90,16 @@ provision_method: "idrac"
 provision_state: "stateful"
 
 # This is the operating system image that will be used for provisioning compute nodes in the cluster.
-# Accepted values: rocky, centos
+# Accepted values: rocky, centos, leap
 # Default value: "rocky"
 # Required field
 provision_os: "rocky"
 
 # This is the path where the user has to place the iso image that needs to be provisioned in target nodes.
-# The iso file should be Rocky8-Minimal or CentOS7-2009-minimal edition.
+# The iso file should be Rocky8-Minimal or CentOS7-2009-minimal or openSUSE-Leap-15.3-DVD edition.
 # Other iso files are not supported.
 # Required field
-iso_file_path: "/root/Rocky-8.4-x86_64-minimal.iso"
+iso_file_path: "/root/Rocky-8.5-x86_64-minimal.iso"
 
 # This is the timezone that will be set during provisioning of OS
 # Available timezones are provided in control_plane/common/files/timezone.txt
@@ -165,4 +175,4 @@ ib_network_nic: "ib0"
 # The dhcp range for assigning the IPv4 address
 # Example: 172.17.0.1
 ib_network_dhcp_start_range: "172.25.0.100"
-ib_network_dhcp_end_range: "172.25.0.200"
+ib_network_dhcp_end_range: "172.25.0.200"

+ 26 - 2
control_plane/input_params/login_vars.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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.
@@ -48,6 +48,19 @@ idrac_password: ""
 # The password must not contain -,\, ',"
 #awx_password: ""
 
+### Usage: webui_grafana ###
+
+# The username for grafana UI
+# The length of username should be at least 5
+# The username must not contain -,\, ',"
+grafana_username: ""
+
+# Password used for grafana UI
+# The length of the password should be at least 5
+# The password must not contain -,\, ',"
+# The password should not be kept 'admin'
+grafana_password: ""
+
 ### Usage: network_ethernet ###
 
 # The username for ethernet switch
@@ -78,4 +91,15 @@ powervault_me4_username: ""
 # The password should have atleast one uppercase character, one lowercase character,
 # one numeric character and one non-alphanumeric character.
 # The password must not contain -,\, ',", . , < , comma(,)
-powervault_me4_password: ""
+powervault_me4_password: ""
+
+# The directory server operations require an administrative user.
+# This user is referred to as the Directory Manager and has full access to the Directory for system management tasks
+# and will be added to the instance of directory server created for IPA.
+# The password must be at least 8 characters long
+# The password must not contain -,\, ',"
+directory_manager_password: ""
+
+# The IPA server requires an administrative user, named 'admin'.
+# This user is a regular system account used for IPA server administration
+ipa_admin_password: ""

+ 12 - 12
control_plane/input_params/powervault_me4_vars.yml

@@ -15,7 +15,7 @@
 
 ### Usage: powervault_me4 ###
 
-# This variable indicates the language selection
+# This variable indicates the language of installation
 # Currently, only "English" is supported
 locale: "English"
 
@@ -25,7 +25,7 @@ locale: "English"
 # Optional
 powervault_me4_system_name: "Unintialized_Name"
 
-# Specify the snmp notification level
+# Specifies the minimum snmp notification level used
 # crit: Sends notifications for Critical events only.
 # error: Sends notifications for Error and Critical events.
 # warn: Sends notifications for Warning, Error, and Critical events.
@@ -42,7 +42,7 @@ powervault_me4_snmp_notify_level: "none"
 # Default value: "linear"
 powervault_me4_pool_type: "linear"
 
-# Specify the required RAID Level
+# Specifies the required RAID Level
 # The different RAID levels and the min and max number of disks supported for each RAID are
 # r1/raid1: 2
 # r5/raid5: 3-16
@@ -53,7 +53,7 @@ powervault_me4_pool_type: "linear"
 # Required field
 powervault_me4_raid_levels: "raid1"
 
-# Specify the range of disks
+# Specifies the range of disks
 # Select a range of disks within an enclosure by entering a comma-separated list that contains 
 # the enclosure number and disk range in the Enter Range of Disks text box. 
 # Use the format enclosure-number.disk-range,enclosure-number.disk-range. 
@@ -65,37 +65,37 @@ powervault_me4_raid_levels: "raid1"
 # Required field
 powervault_me4_disk_range: "0.1-2"
 
-# Specify the volume names
+# Specifies the volume names
 # Default value "k8s_volume" and "slurm_volume"
 # Required field
 powervault_me4_k8s_volume_name: "k8s_volume"
 powervault_me4_slurm_volume_name: "slurm_volume"
 
-# Specify the disk group name
+# Specifies the disk group name
 # Required field
 powervault_me4_disk_group_name: "omnia"
 
-# Specify the percentage for partition in disk
+# Specifies the percentage for partition in disk
 # Default value is "60%"
 # Min: 5
 # Max: 90
 # Required field
 powervault_me4_disk_partition_size: "60"
 
-# Specify the volume size
+# Specifies the volume size
 # Format: 100GB <SizeGB>
 # Default: 100GB
 # Required field
 powervault_me4_volume_size: "100GB"
 
-# Specify the pool for disk and volumes
+# Specifies the pool for disk and volumes
 # Pool can either be  a/A or b/B.
-# Mandatory if powervault_me4_pool_type selected as "virtual".
+# Mandatory if powervault_me4_pool_type selected is "virtual".
 powervault_me4_pool: "a"
 
-# Specify the nic of the server with which Powervault is connected.
+# Specifies the nic of the server with which Powervault is connected.
 # Make sure nfs server also has 3 nics (for internet, OS provision and powervault connection)
-# The nic should be according to the provisioned OS on nfs server.
+# The nic should be specified based on the provisioned OS on nfs server.
 # Example: em1 for CentOS-7, eno1 for RockyOS etc.
 # Default value: "eno1"
 # Required field

+ 23 - 0
control_plane/input_params/security_vars.yml

@@ -0,0 +1,23 @@
+# Copyright 2022 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.
+
+# This variable is used to accept the domain name the user intends to configure
+# Eg: ipa.test
+domain_name: "omnia.test"
+
+# A Kerberos realm is the domain over which a Kerberos authentication server has
+# the authority to authenticate a user, host or service.
+# A realm name is often, but not always the upper case version of the name of the
+# DNS domain over which it presides
+realm_name: "OMNIA.TEST"

+ 1 - 1
control_plane/roles/collect_node_info/vars/main.yml

@@ -22,4 +22,4 @@ file_perm: '0644'
 host_username: root
 host_added_msg: "Added host to awx inventory: "
 host_unreachable_msg: "Following hosts are unreachable: "
-awx_search_key: awx
+awx_search_key: "-job-"

+ 1 - 1
control_plane/roles/control_plane_repo/files/poweredge_models.txt

@@ -14,4 +14,4 @@ R750
 R750xa
 R840
 R940
-R940xa
+R940xa

+ 1 - 5
control_plane/roles/control_plane_common/tasks/count_component_roles.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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.
@@ -16,22 +16,18 @@
   set_fact:
     count_of_manager: "{{ count_of_manager| int + 1 }}"
   when: item == group_name_manager
-  tags: install
 
 - name: Count of compute nodes defined
   set_fact:
     count_of_compute: "{{ count_of_compute| int + 1 }}"
   when: item == group_name_compute
-  tags: install
 
 - name: Count of login nodes defined
   set_fact:
     count_of_login: "{{ count_of_login| int + 1 }}"
   when: item == group_name_login
-  tags: install
 
 - name: Count of NFS nodes defined
   set_fact:
     count_of_nfs_node: "{{ count_of_nfs_node| int + 1 }}"
   when: item == group_name_nfs
-  tags: install

+ 41 - 311
control_plane/roles/control_plane_common/tasks/fetch_base_inputs.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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.
@@ -16,11 +16,13 @@
 - name: Include base variable file base_vars.yml
   include_vars: "{{ base_vars_filename }}"
   no_log: true
+  tags: init
 
 - name: Validate input parameters of base_vars are not empty
   fail:
     msg: "{{ input_base_failure_msg }}"
   register: input_base_check
+  tags: validate
   when:
     - ansible_conf_file_path | length < 1 or
       public_nic | length < 1 or
@@ -38,7 +40,8 @@
       provision_method | length < 1 or
       default_lease_time | length < 1 or
       provision_os | length < 1 or
-      provision_state | length < 1
+      provision_state | length < 1 or
+      mount_location | length < 1
 
 - name: Validate default lease time
   assert:
@@ -48,10 +51,12 @@
       - default_lease_time|int >= 21600
     success_msg: "{{ success_msg_lease_time }}"
     fail_msg: "{{ fail_msg_lease_time }}"
+  tags: [ validate, pxe, network-device, network-ib ]
 
 - name: Calculate max lease time
   set_fact:
     max_lease_time: "{{ default_lease_time|int + 10000 }}"
+  tags: [ init, pxe, network-device, network-ib ]
 
 - name: Validate infiniband base_vars are not empty
   assert:
@@ -63,18 +68,21 @@
     fail_msg: "{{ fail_msg_ib }}"
   register: ib_check
   when: ib_switch_support
+  tags: [ validate, network-ib ]
 
 - name: Set facts to validate snmp support
   set_fact:
     snmp_enabled: false   
     mngmnt_mapping_file: false
     host_mapping_file: false
+  tags: init
 
 - name: Verify snmp_trap_destination IP address
   set_fact:
     snmp_enabled: true
   when: snmp_trap_destination | length > 1
-
+  tags: init
+  
 - name: Assert snmp trap destination address
   assert:
     that:
@@ -84,6 +92,7 @@
     success_msg: "{{ success_snmp_trap_dest }}"
     fail_msg: "{{ fail_snmp_trap_dest }}"
   when: snmp_enabled
+  tags: [ validate, idrac, network-device, network-ib ]
 
 - name: Assert snmp community string
   assert:
@@ -93,11 +102,13 @@
     success_msg: "{{ success_snmp_comm_msg }}"
     fail_msg: "{{ fail_snmp_comm_msg }}"
   when: snmp_enabled
+  tags: [ validate, idrac, network-device, network-ib ]
 
 - name: Check whether ansible config file exists
   stat:
     path: "{{ ansible_conf_file_path }}/ansible.cfg"
   register: ansible_conf_exists
+  tags: init
 
 - name: Create the directory if it does not exist
   file:
@@ -106,6 +117,7 @@
     mode: "{{ file_perm }}"
   when: not ansible_conf_exists.stat.exists
   changed_when: false
+  tags: init
 
 - name: Create ansible config file if it does not exist
   copy:
@@ -115,6 +127,7 @@
       [defaults]
       log_path = /var/log/omnia.log
   when: not ansible_conf_exists.stat.exists
+  tags: init
 
 - name: Assert ethernet_switch_support
   assert:
@@ -122,6 +135,7 @@
       - ethernet_switch_support == true or ethernet_switch_support == false
     success_msg: "{{ ethernet_switch_support_success_msg }}"
     fail_msg: "{{ ethernet_switch_support_fail_msg }}"
+  tags: [ validate, init ]
 
 - name: Assert ib_switch_support
   assert:
@@ -129,6 +143,7 @@
       - ib_switch_support == true or ib_switch_support == false
     success_msg: "{{ ib_switch_support_success_msg }}"
     fail_msg: "{{ ib_switch_support_fail_msg }}"
+  tags: [ validate, init ]
 
 - name: Assert powervault_support
   assert:
@@ -136,23 +151,16 @@
       - powervault_support == true or powervault_support == false
     success_msg: "{{ powervault_support_success_msg }}"
     fail_msg: "{{ powervault_support_fail_msg }}"
+  tags: [ validate, init ]
 
-- name: Fetch the network interfaces in UP state in the system
-  shell: set -o pipefail && ip a | awk '/state UP/{print $2}'
-  register: nic_addr_up
-  changed_when: false
-
-- name: Assert public nic
+- name: Assert enable_security_support
   assert:
     that:
-      - public_nic in nic_addr_up.stdout
-    success_msg: "{{ success_msg_public_nic }}"
-    fail_msg: "{{ fail_msg_public_nic }}"
-
-- name: Fetch the system public IP
-  set_fact:
-    public_ip: "{{ lookup('vars','ansible_'+public_nic).ipv4.address }}"
-
+      - enable_security_support == true or enable_security_support == false
+    success_msg: "{{ enable_security_support_success_msg }}"
+    fail_msg: "{{ enable_security_support_fail_msg }}"
+  tags: [ validate, init ]
+  
 - name: Assert kubernetes pod network CIDR
   assert:
     that:
@@ -161,8 +169,9 @@
       - '"/" in appliance_k8s_pod_net_cidr '
     success_msg: "{{ success_msg_k8s_pod_network_cidr }}"
     fail_msg: "{{ fail_msg_k8s_pod_network_cidr }}"
+  tags: [ validate, init ]
 
-- name: Assert Organization in awx
+- name: Assert organization in awx
   assert:
     that:
       - awx_organization | length >= min_username_length
@@ -173,299 +182,20 @@
       - " \"'\" not in awx_organization "
     success_msg: "{{ success_awx_organization }}"
     fail_msg: "{{ fail_awx_organization }}"
+  tags: [ validate, awx ]
 
-- name: Check timezone file
-  command: grep -Fx "{{ timezone }}" {{ role_path }}/files/timezone.txt
-  failed_when: false
-  register: timezone_out
-  changed_when: false
-
-- name: Assert timezone
-  assert:
-    that: timezone in timezone_out.stdout
-    success_msg: "{{ success_timezone_msg }}"
-    fail_msg: "{{ fail_timezone_msg }}"
-  register: timezone_check
-
-- name: Assert language for provisioning nodes
-  fail:
-    msg: "{{ fail_language }}"
-  when: '"en-US" not in language'
-
-- name: Assert provisioning method
-  assert:
-    that:
-      - provision_method == "PXE" or provision_method == "idrac"
-    success_msg: "{{ success_provision_method }}"
-    fail_msg: "{{ fail_provision_method }}"
-
-- name: Assert provision_state
-  assert:
-    that: 
-      - provision_state == "stateful"
-    fail_msg: "{{ provision_state_fail_msg }}"
-    success_msg: "{{ provision_state_success_msg }}"
-
-- name: Assert operating system
-  assert:
-    that:
-      - provision_os == os_supported_centos or 
-        provision_os == os_supported_rocky
-    fail_msg: "{{ provision_os_fail_msg }}"
-    success_msg: "{{ provision_os_success_msg }}"
-
-- name: Verify the iso_file_path
-  stat:
-    path: "{{ iso_file_path }}"
-  register: result_path_iso_file
-
-- name : Assert iso_file_path location
-  fail:
-    msg: "{{ missing_iso_file_path }}"
-  when: not result_path_iso_file.stat.exists
-
-- name: Validate iso_file_path name
-  assert:
-    that:
-      - result_path_iso_file.stat.exists
-      - '".iso" in iso_file_path'
-      - provision_os in iso_file_path | lower
-    fail_msg: "{{ invalid_iso_file_path }}"
-    success_msg:  "{{ valid_iso_file_path }}"
-
-#### management_net_dhcp_start_end_range
-- name: Assert management network nic
-  assert:
-    that:
-      - mngmnt_network_nic in nic_addr_up.stdout
-    success_msg: "{{ success_msg_mngmnt_network_nic }}"
-    fail_msg: "{{ fail_msg_mngmnt_network_nic }}"
-
-- name: Fetch the management network ip, netmask and subnet
-  set_fact:
-    mngmnt_network_ip: "{{ lookup('vars','ansible_'+mngmnt_network_nic).ipv4.address }}"
-    mngmnt_network_netmask: "{{ lookup('vars','ansible_'+mngmnt_network_nic).ipv4.netmask }}"
-    mngmnt_network_subnet: "{{ lookup('vars','ansible_'+mngmnt_network_nic).ipv4.network }}"
-
-- name: Check the subnet of management network dhcp start range
-  shell: |
-    IFS=. read -r i1 i2 i3 i4 <<< "{{ mngmnt_network_dhcp_start_range }}"
-    IFS=. read -r m1 m2 m3 m4 <<< "{{ mngmnt_network_netmask }}"
-    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
-  args:
-    warn: no
-  register: dhcp_start_mgmnt_result
-  changed_when: false
-
-- name: Set the start dhcp subnet for management network
-  set_fact:
-    dhcp_start_mgmnt: "{{ dhcp_start_mgmnt_result.stdout }}"
-
-- name: Check the subnet of dhcp end range for management network
-  shell: |
-    IFS=. read -r i1 i2 i3 i4 <<< "{{ mngmnt_network_dhcp_end_range }}"
-    IFS=. read -r m1 m2 m3 m4 <<< "{{ mngmnt_network_netmask }}"
-    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
-  register: dhcp_end_mgmnt_result
-  changed_when: false
-
-- name: Set the end dhcp subnet for management network
-  set_fact:
-    dhcp_end_mgmnt: "{{ dhcp_end_mgmnt_result.stdout }}"
-
-- name: Assert management_net_dhcp_start_range
-  assert:
-    that:
-      - mngmnt_network_dhcp_start_range
-      - mngmnt_network_dhcp_start_range | ipv4
-      - mngmnt_network_dhcp_start_range != mngmnt_network_ip
-      - mngmnt_network_dhcp_start_range != mngmnt_network_dhcp_end_range
-      - dhcp_start_mgmnt == mngmnt_network_subnet
-      - dhcp_start_mgmnt == dhcp_end_mgmnt
-    success_msg: "{{ success_dhcp_range }} for management network"
-    fail_msg: "{{ fail_dhcp_range }} for management network"
-
-- name: Assert management_net_dhcp_end_range
-  assert:
-    that:
-      - mngmnt_network_dhcp_end_range
-      - mngmnt_network_dhcp_end_range | ipv4
-      - mngmnt_network_dhcp_end_range != mngmnt_network_ip
-      - mngmnt_network_dhcp_start_range != mngmnt_network_dhcp_end_range
-      - dhcp_end_mgmnt == mngmnt_network_subnet
-      - dhcp_start_mgmnt == dhcp_end_mgmnt
-    success_msg: "{{ success_dhcp_range }} for management network"
-    fail_msg: "{{ fail_dhcp_range }} for management network"
-
-- name: Set the mapping file value for management network
-  set_fact:
-    mngmnt_mapping_file: true
-  when: mngmnt_mapping_file_path | length > 0
-
-- name: Assert valid mngmnt_mapping_file_path
-  stat:
-    path: "{{ mngmnt_mapping_file_path }}"
-  when: mngmnt_mapping_file
-  register: result_mngmnt_mapping_file
-
-- name : Valid mngmnt_mapping_file_path
-  fail:
-    msg: "{{ invalid_mapping_file_path }} for management network"
-  when: mngmnt_mapping_file and not result_mngmnt_mapping_file.stat.exists
-#########
-
-###Host network####
-- name: Fetch the host network ip, netmask and subnet
-  set_fact:
-    hpc_ip: "{{ lookup('vars','ansible_'+host_network_nic).ipv4.address }}"
-    netmask: "{{ lookup('vars','ansible_'+host_network_nic).ipv4.netmask }}"
-    subnet: "{{ lookup('vars','ansible_'+host_network_nic).ipv4.network }}"
-
-- name: Check the subnet of host network dhcp start range
-  shell: |
-    IFS=. read -r i1 i2 i3 i4 <<< "{{ host_network_dhcp_start_range }}"
-    IFS=. read -r m1 m2 m3 m4 <<< "{{ netmask }}"
-    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
-  args:
-    warn: no
-  register: dhcp_start_host_result
-  changed_when: false
-
-- name: Set the start dhcp subnet for host network
-  set_fact:
-    dhcp_start_host: "{{ dhcp_start_host_result.stdout }}"
-
-- name: Check the subnet of dhcp end range for host network
-  shell: |
-    IFS=. read -r i1 i2 i3 i4 <<< "{{ host_network_dhcp_end_range }}"
-    IFS=. read -r m1 m2 m3 m4 <<< "{{ netmask }}"
-    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
-  register: dhcp_end_host_result
-  changed_when: false
-
-- name: Set the end dhcp subnet for host network
-  set_fact:
-    dhcp_end_host: "{{ dhcp_end_host_result.stdout }}"
-
-- name: Assert host_network_dhcp_start_range
-  assert:
-    that:
-      - host_network_dhcp_start_range
-      - host_network_dhcp_start_range | ipv4
-      - host_network_dhcp_start_range != hpc_ip
-      - host_network_dhcp_start_range != host_network_dhcp_end_range
-      - dhcp_start_host == subnet
-      - dhcp_start_host == dhcp_end_host
-    success_msg: "{{ success_dhcp_range }} for host network"
-    fail_msg: "{{ fail_dhcp_range }} for host network"
-
-- name: Assert host_network_dhcp_end_range
-  assert:
-    that:
-      - host_network_dhcp_end_range
-      - host_network_dhcp_end_range | ipv4
-      - host_network_dhcp_end_range != hpc_ip
-      - host_network_dhcp_start_range != host_network_dhcp_end_range
-      - dhcp_end_host == subnet
-      - dhcp_start_host == dhcp_end_host
-    success_msg: "{{ success_dhcp_range }} for host network"
-    fail_msg: "{{ fail_dhcp_range }} for host network"
-
-- name: Set the mapping file value for host network
-  set_fact:
-    host_mapping_file: true
-  when: host_mapping_file_path | length > 0
-  
-- name: Assert valid mapping_file_path
-  stat: 
-    path: "{{ host_mapping_file_path }}"
-  when: host_mapping_file
-  register: result_host_mapping_file
-  
-- name: Valid mapping_file_path
-  fail:
-    msg: "{{ invalid_mapping_file_path }} for host_network"
-  when: host_mapping_file and not result_host_mapping_file.stat.exists
-
-- name: Verify different nics
-  assert:
-    that:
-      - public_nic != mngmnt_network_nic
-      - mngmnt_network_nic != host_network_nic
-      - public_nic != host_network_nic
-    success_msg: "{{ success_msg_different_nics }}"
-    fail_msg: "{{ fail_msg_different_nics }}"
-
-########
-- name: Fetch the infiniband network ip, netmask and subnet
-  set_fact:
-    ib_ip: "{{ lookup('vars','ansible_'+ib_network_nic).ipv4.address }}"
-    ib_netmask: "{{ lookup('vars','ansible_'+ib_network_nic).ipv4.netmask }}"
-    ib_subnet: "{{ lookup('vars','ansible_'+ib_network_nic).ipv4.network }}"
-  when: ib_switch_support
-
-- name: Check the subnet of infiniband network dhcp start range
-  shell: |
-    IFS=. read -r i1 i2 i3 i4 <<< "{{ ib_network_dhcp_start_range }}"
-    IFS=. read -r m1 m2 m3 m4 <<< "{{ ib_netmask }}"
-    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
-  args:
-    warn: no
-  register: dhcp_start_ib_result
-  when: ib_switch_support
-  changed_when: false
-
-- name: Set the start dhcp subnet for infiniband network
-  set_fact:
-    dhcp_start_ib: "{{ dhcp_start_ib_result.stdout }}"
-  when: ib_switch_support
-
-- name: Check the subnet of dhcp end range for infiniband network
-  shell: |
-    IFS=. read -r i1 i2 i3 i4 <<< "{{ ib_network_dhcp_end_range }}"
-    IFS=. read -r m1 m2 m3 m4 <<< "{{ ib_netmask }}"
-    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
-  register: dhcp_end_ib_result
-  when: ib_switch_support
-  changed_when: false
-
-- name: Set the end dhcp subnet for infiniband network
-  set_fact:
-    dhcp_end_ib: "{{ dhcp_end_ib_result.stdout }}"
-  when: ib_switch_support
+- name: Make mount directory for grafana if it doesnt exist
+  file:
+    path: "{{ mount_location }}"
+    state: directory
+    mode: "{{ mount_dir_perm }}"
+    group: root
+    owner: root
+  tags: [ init, monitoring ]
 
-- name: Assert infiniband_net_dhcp_start_range
-  assert:
-    that:
-      - ib_network_dhcp_start_range
-      - ib_network_dhcp_start_range | ipv4
-      - ib_network_dhcp_start_range != ib_ip
-      - ib_network_dhcp_start_range != ib_network_dhcp_end_range
-      - dhcp_start_ib == ib_subnet
-      - dhcp_start_ib == dhcp_end_ib
-    success_msg: "{{ success_dhcp_range }} for infiniband network"
-    fail_msg: "{{ fail_dhcp_range }} for infiniband network"
-  when: ib_switch_support
+- name: Validate provision paramters
+  import_tasks: validate_provision_vars.yml
+  tags: [ validate, idrac, pxe ]
 
-- name: Assert infiniband_net_dhcp_end_range
-  assert:
-    that:
-      - ib_network_dhcp_end_range
-      - ib_network_dhcp_end_range | ipv4
-      - ib_network_dhcp_end_range != ib_ip
-      - ib_network_dhcp_start_range != ib_network_dhcp_end_range
-      - dhcp_end_ib == ib_subnet
-      - dhcp_start_ib == dhcp_end_ib
-    success_msg: "{{ success_dhcp_range }} for infiniband network"
-    fail_msg: "{{ fail_dhcp_range }} for infiniband network"
-  when: ib_switch_support
-
-- name: Verify different nics with infiniband nic
-  assert:
-    that:
-      - public_nic != ib_network_nic
-      - mngmnt_network_nic != ib_network_nic
-      - ib_network_nic != host_network_nic
-    success_msg: "{{ success_msg_different_nics_ib }}"
-    fail_msg: "{{ fail_msg_different_nics_ib }}"
-  when: ib_switch_support
+- name: Validate NIC parameters
+  import_tasks: validate_nic_vars.yml

+ 45 - 0
control_plane/roles/control_plane_common/tasks/fetch_security_inputs.yml

@@ -0,0 +1,45 @@
+# Copyright 2022 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 security variable file security_vars.yml
+  include_vars: "{{ security_vars_filename }}"
+  no_log: true
+  tags: init
+
+- name: Validate input parameters of base_vars are not empty
+  fail:
+    msg: "{{ input_security_failure_msg }}"
+  register: input_base_check
+  tags: [ validate, security ]
+  when:
+    - domain_name | length < 1 or
+      realm_name | length < 1
+
+- name: Validate the domain name
+  assert:
+    that:
+      - domain_name is regex("^(?!-)[A-Za-z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Za-z]{2,}$")
+    success_msg: "{{ dom_name_success_msg }}"
+    fail_msg: "{{ dom_name_fail_msg }}"
+  tags: [ validate, security ]
+
+- name: Validate the realm name
+  assert:
+    that:
+      - realm_name is regex("^(?!-)[A-Z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Z]{2,}$")
+      - '"." in realm_name'
+    success_msg: "{{ realm_success_msg }}"
+    fail_msg: "{{ realm_fail_msg }}"
+  tags: [ validate, security ]

+ 10 - 10
control_plane/roles/control_plane_common/tasks/fetch_sm_inputs.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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.
@@ -17,41 +17,41 @@
   stat:
     path: "{{ ib_config_file }}"
   register: stat_result
-  tags: install
+  tags: init
 
 - name: Fail if config file doesn't exist
   fail:
     msg: "{{ fail_msg_config_file }}"
   when: not stat_result.stat.exists
-  tags: install
+  tags: init
 
 - name: Check that the opensm.conf exists
   stat:
     path: "{{ opensm_conf_file }}"
   register: stat_result
-  tags: install
+  tags: init
 
 - name: Fail if opensm.conf file doesn't exist
   fail:
     msg: "{{ fail_msg_opensm_config_file }}"
   when: not stat_result.stat.exists
-  tags: install
+  tags: init
 
 - name: Include infiniband variable file
   include_vars: "{{ ib_config_file }}"
-  tags: install
+  tags: init
 
 - name: Validate directory input definition
   fail:
     msg: "{{ fail_msg_ib_input_definition }}"
+  tags: [ validate, network-ib ]
   when:
     - subnet_manager.cache_directory is not defined or subnet_manager.log_directory is not defined
-  tags: install
 
 - name: Validate directory input
   fail:
     msg: "{{ fail_msg_ib_input }}"
+  tags: [ validate, network-ib ]
   when:
-    - subnet_manager.cache_directory |length < 1
-    - subnet_manager.log_directory |length < 1
-  tags: install
+    - subnet_manager.cache_directory | length < 1
+    - subnet_manager.log_directory | length < 1

+ 1 - 2
control_plane/roles/control_plane_common/tasks/internet_validation.yml

@@ -1,4 +1,4 @@
-#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -22,4 +22,3 @@
     timeout: "{{ internet_timeout }}"
     msg: "{{ internet_status }}"
   register: internet_value
-  tags: install

+ 21 - 11
control_plane/roles/control_plane_common/tasks/main.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,42 +12,52 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 ---
-- name: Mount Path
-  set_fact:
-    mount_path: "{{ role_path + '/../../..'  }}"
 
 - name: Pre-requisite validation
   import_tasks: pre_requisite.yml
 
 - name: Internet validation
   import_tasks: internet_validation.yml
+  tags: init
 
 - name: Common packages installation
   import_tasks: package_installation.yml
+  tags: init
 
-- name: Basic Configuration
+- name: Basic configuration
   import_tasks: fetch_base_inputs.yml
 
-- name: Credentials Configuration
-  import_tasks: password_config.yml
-
-- name: omnia inputs validation
+- name: Omnia inputs validation
   import_tasks: verify_omnia_params.yml
 
+- name: Credentials inputs validation
+  import_tasks: verify_login_inputs.yml
+
+- name: iDRAC inputs validation
+  import_tasks: validate_idrac_vars.yml
+
 - name: Subnet manager inputs validation
   import_tasks: fetch_sm_inputs.yml
   when: ib_switch_support
 
+- name: Security inputs validation
+  import_tasks: fetch_security_inputs.yml
+  when: enable_security_support
+
 - name: Host mapping file validation
   import_tasks: validate_host_mapping_file.yml
-  when: host_mapping_file_path |length >0
+  when: host_mapping_file_path | length > 0
+  tags: [ validate, pxe ]
 
 - name: Device mapping file validation
   import_tasks: validate_device_mapping_file.yml
-  when: mngmnt_mapping_file_path |length >0
+  when: mngmnt_mapping_file_path | length > 0
+  tags: [ validate, network-device ]
 
 - name: Encrypt idrac_tools_vars.yml
   import_tasks: encrypt_idrac_tools_vars.yml
+  tags: init
 
 - name: NFS Server setup for offline repo and awx
   import_tasks: nfs_server_setup.yml
+  tags: init

+ 12 - 6
control_plane/roles/control_plane_common/tasks/package_installation.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,14 +12,20 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 ---
+- name: Install packages - leap
+  zypper:
+    name: "{{ common_packages_leap }}"
+    state: present
+  when: ( os_supported_leap in mgmt_os ) and ( ansible_distribution_version >= os_supported_leap_version )
 
-- name: Install packages
+- name: Install packages - rocky
   package:
     name: "{{ common_packages }}"
     state: present
-  tags: install
-  
+  when:
+    - ( mgmt_os == os_supported_centos ) and ( ansible_distribution_version >= os_supported_centos_version ) or
+      ( mgmt_os == os_supported_rocky ) and ( ansible_distribution_version >= os_supported_rocky_version )
+
 - name: Install netaddr
   command: pip3 install netaddr
-  tags: install
-  changed_when: false
+  changed_when: false

+ 65 - 25
control_plane/roles/control_plane_common/tasks/pre_requisite.yml

@@ -1,4 +1,4 @@
-#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,16 +13,51 @@
 #  limitations under the License.
 ---
 
+- name: Validate skip tags
+  fail:
+    msg: "{{ invalid_skip_tag_msg }}"
+  tags: [ network-device, pxe, awx, network-ib, idrac, monitoring, security, firmware-repo, templates ]
+  when:
+    - '"init" in ansible_skip_tags'
+
+- name: Validate run tags
+  fail:
+    msg: "{{ invalid_run_tag_msg }}"
+  when:
+    - '"init" not in ansible_run_tags'
+    - '"all" not in ansible_run_tags'
+  tags: [ init, network-device, pxe, awx, network-ib, idrac, monitoring, security, firmware-repo, templates ]
+
+- name: Mount Path
+  set_fact:
+    mount_path: "{{ role_path + '/../../..'  }}"
+  tags: init
+    
+- name: Collecting ansible python version
+  shell:
+    cmd: ansible --version | grep "python version" | cut -d ' ' -f 6
+  register: ansible_python_version
+  changed_when: false
+  tags: init
+
+- name: Saving management station os
+  set_fact:
+    mgmt_os: "{{ ansible_facts['distribution'] | lower }}"
+  tags: init
+
 - name: Verify the ansible and python versions installed
   fail:
     msg: "{{ ansible_python_version_status }}"
-  when: ansible_python_version != python_version_support
-  tags: install
+  tags: init
+  when:
+    - ansible_python_version.stdout != python_version_leap
+    - ansible_python_version.stdout != python_version_support
 
 - name: Verify whether ansible configuration file exists
   stat:
     path: "{{ default_ansible_config_file_path }}"
   register: file_exists
+  tags: init
 
 - name: Set omnia.log file
   replace:
@@ -30,40 +65,45 @@
     regexp: '#log_path = /var/log/ansible.log'
     replace: 'log_path = /var/log/omnia.log'
   when: file_exists.stat.exists
-  tags: install
+  tags: init
 
 - name: Check OS support
   assert:
     that:
-      - ( ansible_distribution | lower == os_supported_centos ) and ( ansible_distribution_version >= os_supported_centos_version ) or
-        ( ansible_distribution | lower == os_supported_rocky ) and ( ansible_distribution_version >= os_supported_rocky_version )
+      - ( mgmt_os == os_supported_centos ) and ( ansible_distribution_version >= os_supported_centos_version ) or
+        ( mgmt_os == os_supported_rocky ) and ( ansible_distribution_version >= os_supported_rocky_version ) or
+        ( os_supported_leap in mgmt_os ) and ( ansible_distribution_version >= os_supported_leap_version )
     fail_msg: "{{ fail_os_status }}"
     success_msg: "{{ success_os_status }}"
   register: os_value
-  tags: install
+  tags: init
 
-- name: Fetch SElinux mode
-  command: sestatus
-  register: sestatus_current
-  changed_when: false
+- block:
+    - name: Fetch SElinux mode
+      command: sestatus
+      register: sestatus_current
+      changed_when: false
 
-- name: Disable SElinux
-  replace:
-    path: /etc/sysconfig/selinux
-    regexp: 'SELINUX=[a-z]+'
-    replace: 'SELINUX=disabled'
-  when: '"SELinux status:                 enabled" in sestatus_current.stdout_lines'
-  tags: install
+    - name: Disable SElinux
+      replace:
+        path: /etc/sysconfig/selinux
+        regexp: 'SELINUX=[a-z]+'
+        replace: 'SELINUX=disabled'
+      when: '"SELinux status: enabled" in sestatus_current.stdout_lines'
 
-- name: Status of SElinux
-  fail:
-    msg: "{{ selinux_status }}"
-  when: '"SELinux status:                 enabled" in sestatus_current.stdout_lines'
-  register: selinux_value
-  tags: install
+    - name: Status of SElinux
+      fail:
+        msg: "{{ selinux_status }}"
+      when: '"SELinux status: enabled" in sestatus_current.stdout_lines'
+      register: selinux_value
+  tags: init
+  when:
+    - ( mgmt_os == os_supported_centos ) and ( ansible_distribution_version >= os_supported_centos_version ) or
+      ( mgmt_os == os_supported_rocky ) and ( ansible_distribution_version >= os_supported_rocky_version )
 
 - name: State of firewall
   service:
     name: firewalld
     state: started
-    enabled: yes
+    enabled: yes
+  tags: init

+ 1 - 11
control_plane/roles/control_plane_common/tasks/validate_device_mapping_file.yml

@@ -11,17 +11,16 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # limitations under the License.
 ---
+
 - name: Check that device mapping file exists at mentioned path
   stat:
     path: "{{ mngmnt_mapping_file_path }}"
   register: stat_result
-  tags: install
 
 - name: Fail if config file doesn't exist
   fail:
     msg: "{{ fail_msg_mapping_file + mngmnt_mapping_file_path }}"
   when: not stat_result.stat.exists
-  tags: install
 
 - name: Read device mapping file from CSV file and return a dictionary
   read_csv:
@@ -29,38 +28,32 @@
     key: "{{ mapping_file_key }}"
   register: device_mapping_file
   delegate_to: localhost
-  tags: install
 
 - name: Check if header is present in mapping file
   shell:  set -o pipefail && awk 'NR==1 { print $1}' "{{ mngmnt_mapping_file_path }}"
   register: mngmnt_header
   changed_when: false
-  tags: install
 
 - name: Fail if header not in correct format
   fail:
     msg: "{{ fail_device_mapping_file_header }}"
   when: mngmnt_header.stdout !=  device_mapping_header_format
-  tags: install
 
 - name: Check if mapping file is comma seperated
   shell: awk -F\, '{print NF-1}' "{{ mngmnt_mapping_file_path }}"
   register: mngmnt_comma_seperated
   changed_when: false
-  tags: install
 
 - name: Fail if not comma seperated or if all fields are not given
   fail:
     msg: "{{ fail_mapping_file_field_seperation }}"
   when: not(item =="1")
   with_items: "{{ mngmnt_comma_seperated.stdout_lines }}"
-  tags: install
 
 - name: Initialize count variables
   set_fact:
     list_of_ips: []
     count_total_items: "{{ device_mapping_file.dict |length }}"
-  tags: install
 
 - name: Create list of IPs in mapping file
   set_fact:
@@ -68,15 +61,12 @@
   loop: "{{ device_mapping_file.dict | dict2items }}"
   loop_control:
     label: "{{ item.value.MAC }}"
-  tags: install
 
 - name: Find count of unique IPs
   set_fact:
     count_of_unique_ip : "{{ list_of_ips| unique| length }}"
-  tags: install
 
 - name: Validation to check if unique IPs are provided for each node
   fail:
     msg: "{{ fail_mapping_file_duplicate_ip + mngmnt_mapping_file_path }}"
   when: not(count_of_unique_ip|int == count_total_items|int)
-  tags: install

+ 1 - 21
control_plane/roles/control_plane_common/tasks/validate_host_mapping_file.yml

@@ -11,17 +11,16 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # limitations under the License.
 ---
+
 - name: Check that host mapping file exists at mentioned path
   stat:
     path: "{{ host_mapping_file_path }}"
   register: stat_result
-  tags: install
 
 - name: Fail if config file doesn't exist
   fail:
     msg: "{{ fail_msg_mapping_file + host_mapping_file_path }}"
   when: not stat_result.stat.exists
-  tags: install
 
 - name: Read host mapping file from CSV file and return a dictionary
   read_csv:
@@ -29,50 +28,42 @@
     key: "{{ mapping_file_key }}"
   register: mapping_file
   delegate_to: localhost
-  tags: install
 
 - name: Initialize variable for role support in mapping file
   set_fact:
     component_role_support: false
-  tags: install
 
 - name: Check if header is present in mapping file
   shell:  set -o pipefail && awk 'NR==1 { print $1}' "{{ host_mapping_file_path }}"
   register: mngmnt_header
   changed_when: false
-  tags: install
 
 - name: Fail if header not in correct format
   assert:
     that: (mngmnt_header.stdout ==  host_mapping_header_format) or (mngmnt_header.stdout == host_mapping_header_with_role_format)
     fail_msg: "{{ fail_mapping_file_header }}"
-  tags: install
 
 - name: Check if mapping file is comma seperated
   shell: awk -F\, '{print NF-1}' "{{ host_mapping_file_path }}"
   register: mngmnt_comma_seperated
   changed_when: false
-  tags: install
 
 - name: Set variable if component roles given in mapping file
   set_fact:
     component_role_support: true
   when: mngmnt_header.stdout == host_mapping_header_with_role_format
-  tags: install
 
 - name: Fail if not comma seperated or if all fields are not given for MAC,Hostname,IP,Component_role
   fail:
     msg: "{{ fail_mapping_file_field_seperation }}"
   when: not(item =="3") and not (item == "-1") and component_role_support
   with_items: "{{ mngmnt_comma_seperated.stdout_lines }}"
-  tags: install
 
 - name: Fail if not comma seperated or if all fields are not given for MAC,Hostname,IP
   fail:
     msg: "{{ fail_mapping_file_field_seperation }}"
   when: not(item =="2") and not (item == "-1") and not(component_role_support)
   with_items: "{{ mngmnt_comma_seperated.stdout_lines }}"
-  tags: install
 
 - name: Initialize count variables
   set_fact:
@@ -84,7 +75,6 @@
     count_of_nfs_node: 0
     count_of_login: 0
     count_total_items: "{{ mapping_file.dict |length }}"
-  tags: install
 
 - name: Create list of IPs and component roles and hostnames defined in mapping file
   set_fact:
@@ -93,7 +83,6 @@
   loop: "{{ mapping_file.dict | dict2items }}"
   loop_control:
     label: "{{ item.value.MAC }}"
-  tags: install
 
 - name: Create list of component roles defined in mapping file
   set_fact:
@@ -102,7 +91,6 @@
   loop_control:
     label: "{{ item.value.MAC }}"
   when: component_role_support
-  tags: install
 
 - name: Assert hostnames
   assert:
@@ -113,35 +101,29 @@
     quiet: yes
     fail_msg: "{{ fail_mapping_file_hostname_chars + item }}"
   with_items: "{{ list_of_hostnames }}"
-  tags: install
 
 - name: Find count of unique IPs
   set_fact:
     count_of_unique_ip : "{{ list_of_ips| unique| length }}"
-  tags: install
 
 - name: Validation to check if unique IPs are provided for each node
   fail:
     msg: "{{ fail_mapping_file_duplicate_ip + host_mapping_file_path }}"
   when: not(count_of_unique_ip|int == count_total_items|int)
-  tags: install
 
 - name: Find count of unique hostnames
   set_fact:
     count_of_unique_hostnames : "{{ list_of_hostnames | unique | length }}"
-  tags: install
 
 - name: Validation to check if unique hostnames are provided for each node
   fail:
     msg: "{{ fail_mapping_file_duplicate_hostname }}"
   when: not(count_of_unique_hostnames|int == count_total_items| int)
-  tags: install
 
 - name: Find count of each component role defined in mapping file
   include_tasks: count_component_roles.yml
   loop: "{{ list_of_roles }}"
   when: component_role_support
-  tags: install
 
 - block:
   - name: Validation to check if component roles for each node is defined
@@ -168,12 +150,10 @@
     fail:
       msg: "{{ fail_mapping_file_nfs_role }}"
     when: (not (count_of_nfs_node|int == 1) and powervault_support) or ((count_of_nfs_node|int == 1) and not powervault_support)
-  tags: install
 
   rescue:
   - name: Count of roles defined
     fail:
       msg: "{{ count_of_roles_defined }}"
-    tags: install
 
   when: component_role_support

+ 45 - 0
control_plane/roles/control_plane_common/tasks/validate_idrac_vars.yml

@@ -0,0 +1,45 @@
+# Copyright 2022 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
+  tags: init
+
+- 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 }}"
+  tags: [ validate, firmware-repo ]
+
+- name: Read poweredge_model file
+  command: cat {{ role_path }}/files/poweredge_models.txt
+  failed_when: false
+  register: poweredge_models_file_output
+  changed_when: false
+  tags: [ validate, firmware-repo ]
+
+- name: Assert poweredge_model value
+  assert:
+    that:
+      - item | length > 1
+      - item in poweredge_models_file_output.stdout
+    success_msg: "{{ poweredge_model_success_msg }}"
+    fail_msg: "{{ poweredge_model_fail_msg }}"
+  when: firmware_update_required
+  with_items: "{{ poweredge_model.split(',') | map('trim') }}"
+  tags: [ validate, firmware-repo ]

+ 299 - 0
control_plane/roles/control_plane_common/tasks/validate_nic_vars.yml

@@ -0,0 +1,299 @@
+# Copyright 2022 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: Fetch the network interfaces in UP state in the system
+  shell: set -o pipefail && ip a | awk '/state UP/{print $2}'
+  register: nic_addr_up
+  changed_when: false
+  tags: init
+
+### public network
+
+- name: Assert public nic
+  assert:
+    that:
+      - public_nic in nic_addr_up.stdout
+    success_msg: "{{ success_msg_public_nic }}"
+    fail_msg: "{{ fail_msg_public_nic }}"
+  tags: [ validate, init ]
+
+- name: Fetch the system public IP
+  set_fact:
+    public_ip: "{{ lookup('vars','ansible_'+public_nic).ipv4.address }}"
+  tags: init
+
+### management network
+
+- name: Assert management network nic
+  assert:
+    that:
+      - mngmnt_network_nic in nic_addr_up.stdout
+    success_msg: "{{ success_msg_mngmnt_network_nic }}"
+    fail_msg: "{{ fail_msg_mngmnt_network_nic }}"
+  tags: [ validate, network-device ]
+
+- name: Fetch the management network ip, netmask and subnet
+  set_fact:
+    mngmnt_network_ip: "{{ lookup('vars','ansible_'+mngmnt_network_nic).ipv4.address }}"
+    mngmnt_network_netmask: "{{ lookup('vars','ansible_'+mngmnt_network_nic).ipv4.netmask }}"
+    mngmnt_network_subnet: "{{ lookup('vars','ansible_'+mngmnt_network_nic).ipv4.network }}"
+  tags: init
+
+- name: Check the subnet of management network dhcp start range
+  shell: |
+    IFS=. read -r i1 i2 i3 i4 <<< "{{ mngmnt_network_dhcp_start_range }}"
+    IFS=. read -r m1 m2 m3 m4 <<< "{{ mngmnt_network_netmask }}"
+    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
+  args:
+    warn: no
+  register: dhcp_start_mgmnt_result
+  changed_when: false
+  tags: init
+
+- name: Set the start dhcp subnet for management network
+  set_fact:
+    dhcp_start_mgmnt: "{{ dhcp_start_mgmnt_result.stdout }}"
+  tags: init
+
+- name: Check the subnet of dhcp end range for management network
+  shell: |
+    IFS=. read -r i1 i2 i3 i4 <<< "{{ mngmnt_network_dhcp_end_range }}"
+    IFS=. read -r m1 m2 m3 m4 <<< "{{ mngmnt_network_netmask }}"
+    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
+  register: dhcp_end_mgmnt_result
+  changed_when: false
+  tags: init
+
+- name: Set the end dhcp subnet for management network
+  set_fact:
+    dhcp_end_mgmnt: "{{ dhcp_end_mgmnt_result.stdout }}"
+  tags: init
+
+- name: Assert management_net_dhcp_start_range
+  assert:
+    that:
+      - mngmnt_network_dhcp_start_range |  length > 1
+      - mngmnt_network_dhcp_start_range | ipv4
+      - mngmnt_network_dhcp_start_range != mngmnt_network_ip
+      - mngmnt_network_dhcp_start_range != mngmnt_network_dhcp_end_range
+      - dhcp_start_mgmnt == mngmnt_network_subnet
+      - dhcp_start_mgmnt == dhcp_end_mgmnt
+    success_msg: "{{ success_dhcp_range }} for management network"
+    fail_msg: "{{ fail_dhcp_range }} for management network"
+  tags: [ validate, network-device ]
+
+- name: Assert management_net_dhcp_end_range
+  assert:
+    that:
+      - mngmnt_network_dhcp_end_range |  length > 1
+      - mngmnt_network_dhcp_end_range | ipv4
+      - mngmnt_network_dhcp_end_range != mngmnt_network_ip
+      - mngmnt_network_dhcp_start_range != mngmnt_network_dhcp_end_range
+      - dhcp_end_mgmnt == mngmnt_network_subnet
+      - dhcp_start_mgmnt == dhcp_end_mgmnt
+    success_msg: "{{ success_dhcp_range }} for management network"
+    fail_msg: "{{ fail_dhcp_range }} for management network"
+  tags: [ validate, network-device ]
+
+- name: Set the mapping file value for management network
+  set_fact:
+    mngmnt_mapping_file: true
+  when: mngmnt_mapping_file_path | length > 0
+  tags: init
+
+- name: Assert valid mngmnt_mapping_file_path
+  stat:
+    path: "{{ mngmnt_mapping_file_path }}"
+  when: mngmnt_mapping_file
+  register: result_mngmnt_mapping_file
+  tags: init
+
+- name : Valid mngmnt_mapping_file_path
+  fail:
+    msg: "{{ invalid_mapping_file_path }} for management network"
+  when: mngmnt_mapping_file and not result_mngmnt_mapping_file.stat.exists
+  tags: init
+
+### host network
+
+- name: Fetch the host network ip, netmask and subnet
+  set_fact:
+    hpc_ip: "{{ lookup('vars','ansible_'+host_network_nic).ipv4.address }}"
+    netmask: "{{ lookup('vars','ansible_'+host_network_nic).ipv4.netmask }}"
+    subnet: "{{ lookup('vars','ansible_'+host_network_nic).ipv4.network }}"
+  tags: init
+
+- name: Check the subnet of host network dhcp start range
+  shell: |
+    IFS=. read -r i1 i2 i3 i4 <<< "{{ host_network_dhcp_start_range }}"
+    IFS=. read -r m1 m2 m3 m4 <<< "{{ netmask }}"
+    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
+  args:
+    warn: no
+  register: dhcp_start_host_result
+  changed_when: false
+  tags: init
+
+- name: Set the start dhcp subnet for host network
+  set_fact:
+    dhcp_start_host: "{{ dhcp_start_host_result.stdout }}"
+  tags: init
+
+- name: Check the subnet of dhcp end range for host network
+  shell: |
+    IFS=. read -r i1 i2 i3 i4 <<< "{{ host_network_dhcp_end_range }}"
+    IFS=. read -r m1 m2 m3 m4 <<< "{{ netmask }}"
+    printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
+  register: dhcp_end_host_result
+  changed_when: false
+  tags: init
+
+- name: Set the end dhcp subnet for host network
+  set_fact:
+    dhcp_end_host: "{{ dhcp_end_host_result.stdout }}"
+  tags: init
+
+- name: Assert host_network_dhcp_start_range
+  assert:
+    that:
+      - host_network_dhcp_start_range | length > 1
+      - host_network_dhcp_start_range | ipv4
+      - host_network_dhcp_start_range != hpc_ip
+      - host_network_dhcp_start_range != host_network_dhcp_end_range
+      - dhcp_start_host == subnet
+      - dhcp_start_host == dhcp_end_host
+    success_msg: "{{ success_dhcp_range }} for host network"
+    fail_msg: "{{ fail_dhcp_range }} for host network"
+  tags: [ validate, pxe ]
+
+- name: Assert host_network_dhcp_end_range
+  assert:
+    that:
+      - host_network_dhcp_end_range | length > 1
+      - host_network_dhcp_end_range | ipv4
+      - host_network_dhcp_end_range != hpc_ip
+      - host_network_dhcp_start_range != host_network_dhcp_end_range
+      - dhcp_end_host == subnet
+      - dhcp_start_host == dhcp_end_host
+    success_msg: "{{ success_dhcp_range }} for host network"
+    fail_msg: "{{ fail_dhcp_range }} for host network"
+  tags: [ validate, pxe ]
+
+- name: Set the mapping file value for host network
+  set_fact:
+    host_mapping_file: true
+  when: host_mapping_file_path | length > 0
+  tags: init
+  
+- name: Assert valid mapping_file_path
+  stat: 
+    path: "{{ host_mapping_file_path }}"
+  when: host_mapping_file
+  register: result_host_mapping_file
+  tags: init
+  
+- name: Valid mapping_file_path
+  fail:
+    msg: "{{ invalid_mapping_file_path }} for host_network"
+  when: host_mapping_file and not result_host_mapping_file.stat.exists
+  tags: init
+
+- name: Verify different nics
+  assert:
+    that:
+      - public_nic != mngmnt_network_nic
+      - mngmnt_network_nic != host_network_nic
+      - public_nic != host_network_nic
+    success_msg: "{{ success_msg_different_nics }}"
+    fail_msg: "{{ fail_msg_different_nics }}"
+  tags: [ validate, pxe, network-device ]
+
+### ib network
+
+- name: Validate ib network vars
+  block:
+    - name: Fetch the infiniband network ip, netmask and subnet
+      set_fact:
+        ib_ip: "{{ lookup('vars','ansible_'+ib_network_nic).ipv4.address }}"
+        ib_netmask: "{{ lookup('vars','ansible_'+ib_network_nic).ipv4.netmask }}"
+        ib_subnet: "{{ lookup('vars','ansible_'+ib_network_nic).ipv4.network }}"
+      tags: init
+      
+    - name: Check the subnet of infiniband network dhcp start range
+      shell: |
+        IFS=. read -r i1 i2 i3 i4 <<< "{{ ib_network_dhcp_start_range }}"
+        IFS=. read -r m1 m2 m3 m4 <<< "{{ ib_netmask }}"
+        printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
+      args:
+        warn: no
+      register: dhcp_start_ib_result  
+      changed_when: false
+      tags: init
+
+    - name: Set the start dhcp subnet for infiniband network
+      set_fact:
+        dhcp_start_ib: "{{ dhcp_start_ib_result.stdout }}"
+      tags: init    
+
+    - name: Check the subnet of dhcp end range for infiniband network
+      shell: |
+        IFS=. read -r i1 i2 i3 i4 <<< "{{ ib_network_dhcp_end_range }}"
+        IFS=. read -r m1 m2 m3 m4 <<< "{{ ib_netmask }}"
+        printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
+      register: dhcp_end_ib_result  
+      changed_when: false
+      tags: init
+
+    - name: Set the end dhcp subnet for infiniband network
+      set_fact:
+        dhcp_end_ib: "{{ dhcp_end_ib_result.stdout }}"
+      tags: init
+
+    - name: Assert infiniband_net_dhcp_start_range
+      assert:
+        that:
+          - ib_network_dhcp_start_range | length > 1
+          - ib_network_dhcp_start_range | ipv4
+          - ib_network_dhcp_start_range != ib_ip
+          - ib_network_dhcp_start_range != ib_network_dhcp_end_range
+          - dhcp_start_ib == ib_subnet
+          - dhcp_start_ib == dhcp_end_ib
+        success_msg: "{{ success_dhcp_range }} for infiniband network"
+        fail_msg: "{{ fail_dhcp_range }} for infiniband network"
+      tags: [ validate, network-ib ]
+  
+    - name: Assert infiniband_net_dhcp_end_range
+      assert:
+        that:
+          - ib_network_dhcp_end_range | length > 1
+          - ib_network_dhcp_end_range | ipv4
+          - ib_network_dhcp_end_range != ib_ip
+          - ib_network_dhcp_start_range != ib_network_dhcp_end_range
+          - dhcp_end_ib == ib_subnet
+          - dhcp_start_ib == dhcp_end_ib
+        success_msg: "{{ success_dhcp_range }} for infiniband network"
+        fail_msg: "{{ fail_dhcp_range }} for infiniband network"
+      tags: [ validate, network-ib ]
+
+    - name: Verify different nics with infiniband nic
+      assert:
+        that:
+          - public_nic != ib_network_nic
+          - mngmnt_network_nic != ib_network_nic
+          - ib_network_nic != host_network_nic
+        success_msg: "{{ success_msg_different_nics_ib }}"
+        fail_msg: "{{ fail_msg_different_nics_ib }}"
+      tags: [ validate, pxe, network-ib, network-device ]
+  when: ib_switch_support

+ 81 - 0
control_plane/roles/control_plane_common/tasks/validate_provision_vars.yml

@@ -0,0 +1,81 @@
+# Copyright 2022 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: Convert timezone.txt to linux format
+  command: dos2unix {{ role_path }}/files/timezone.txt
+  failed_when: false
+  changed_when: false
+
+- name: Searching for timezone
+  lineinfile:
+    path: "{{ role_path }}/files/timezone.txt"
+    line: "{{ timezone }}"
+    state: present
+  check_mode: yes
+  register: timezone_search
+
+- name: Assert timezone
+  assert:
+    that: timezone_search is not changed
+    success_msg: "{{ success_timezone_msg }}"
+    fail_msg: "{{ fail_timezone_msg }}"
+  register: timezone_check
+
+- name: Assert language for provisioning nodes
+  fail:
+    msg: "{{ fail_language }}"
+  when: '"en-US" not in language'
+
+- name: Assert provisioning method
+  assert:
+    that:
+      - provision_method == "PXE" or provision_method == "idrac"
+    success_msg: "{{ success_provision_method }}"
+    fail_msg: "{{ fail_provision_method }}"
+
+- name: Assert provision_state
+  assert:
+    that: 
+      - provision_state == "stateful"
+    fail_msg: "{{ provision_state_fail_msg }}"
+    success_msg: "{{ provision_state_success_msg }}"
+
+- name: Assert operating system
+  assert:
+    that:
+      - provision_os == os_supported_centos or 
+        provision_os == os_supported_rocky or
+        provision_os == os_supported_leap
+    fail_msg: "{{ provision_os_fail_msg }}"
+    success_msg: "{{ provision_os_success_msg }}"
+
+- name: Verify the iso_file_path
+  stat:
+    path: "{{ iso_file_path }}"
+  register: result_path_iso_file
+
+- name : Assert iso_file_path location
+  fail:
+    msg: "{{ missing_iso_file_path }}"
+  when: not result_path_iso_file.stat.exists
+
+- name: Validate iso_file_path name
+  assert:
+    that:
+      - result_path_iso_file.stat.exists
+      - '".iso" in iso_file_path'
+      - provision_os in iso_file_path | lower
+    fail_msg: "{{ invalid_iso_file_path }}"
+    success_msg:  "{{ valid_iso_file_path }}"

+ 77 - 1
control_plane/roles/control_plane_common/tasks/password_config.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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.
@@ -18,6 +18,7 @@
   changed_when: false
   register: config_content
   no_log: true
+  tags: init
 
 - name: Decrpyt login_vars.yml
   command: >-
@@ -25,10 +26,12 @@
     --vault-password-file {{ vault_filename }}
   changed_when: false
   when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+  tags: init
 
 - name: Include variable file login_vars.yml
   include_vars: "{{ login_vars_filename }}"
   no_log: true
+  tags: init
 
 - name: Validate input parameters are not empty
   fail:
@@ -39,6 +42,16 @@
       cobbler_password | length < 1 or      
       idrac_username | length < 1 or
       idrac_password | length < 1
+  tags: [ validate, pxe, idrac ]
+
+- name: Validate security parameters when enable_security_support is set to true
+  fail:
+    msg: "{{ login_input_config_failure_msg }} for ipa server installation"
+  tags: [ validate, security ]
+  when:
+    - ( directory_manager_password | length < 1 or
+      ipa_admin_password | length < 1 ) and
+      enable_security_support
 
 - name: Assert provision credentials
   block:
@@ -56,6 +69,7 @@
     - name: Provision password validation check
       fail:
         msg: "{{ fail_msg_provision_password }}"
+  tags: [ validate, pxe, idrac ]
 
 - name: Assert cobbler credentials
   block:
@@ -73,6 +87,7 @@
     - name: Cobbler password validation check
       fail:
         msg: "{{ fail_msg_cobbler_password }}"
+  tags: [ validate, pxe ]
 
 - name: Assert idrac credentials
   block:
@@ -96,6 +111,32 @@
     - name: idrac credentials validation check
       fail:
         msg: "{{ fail_msg_idrac_credentials }}"
+  tags: [ validate, idrac ]
+
+- name: Assert grafana credentials
+  block:
+    - name: Assert grafana_username and grafana_username
+      assert:
+        that:
+          - grafana_username | length >= min_length_grafana
+          - grafana_username | length <= max_length
+          - '"-" not in grafana_username '
+          - '"\\" not in grafana_username '
+          - '"\"" not in grafana_username '
+          - " \"'\" not in grafana_username "
+          - grafana_password | length >= min_length_grafana
+          - grafana_password | length <= max_length
+          - not grafana_password == 'admin'
+          - '"-" not in grafana_password '
+          - '"\\" not in grafana_password '
+          - '"\"" not in grafana_password '
+          - " \"'\" not in grafana_password "
+      no_log: true
+  rescue:
+    - name: grafana credentials validation check
+      fail:
+        msg: "{{ fail_msg_grafana_credentials }}"
+  tags: [ validate, monitoring ]
 
 - name: Assert username and password for ethernet switches
   block:
@@ -120,6 +161,7 @@
       fail:
         msg: "{{ fail_msg_ethernet_credentials }}"
   when: ethernet_switch_support
+  tags: [ validate, network-device ]
 
 - name: Assert username and password for IB switches
   block:
@@ -144,6 +186,7 @@
       fail:
         msg: "{{ fail_msg_ib_credentials }}"
   when: ib_switch_support
+  tags: [ validate, network-ib ]
 
 - name: Assert username and password for powervault me4
   block:
@@ -175,11 +218,41 @@
       fail:
         msg: "{{ fail_msg_me4_credentials }}"
   when: powervault_support
+  tags: [ validate, network-device ]
+
+- name: Assert directory_manager_password
+  assert:
+    that:
+      - directory_manager_password | length > min_length | int - 1
+      - directory_manager_password | length < max_length | int + 1
+      - '"-" not in directory_manager_password '
+      - '"\\" not in directory_manager_password '
+      - '"\"" not in directory_manager_password '
+      - " \"'\" not in directory_manager_password "
+    success_msg: "{{ success_msg_dir_manager_password }}"
+    fail_msg: "{{ fail_msg_dir_manager_password }}"
+  when: enable_security_support
+  tags: [ validate, security ]
+
+- name: Assert ipa_admin_password
+  assert:
+    that:
+      - ipa_admin_password | length > min_length | int - 1
+      - ipa_admin_password | length < max_length | int + 1
+      - '"-" not in ipa_admin_password '
+      - '"\\" not in ipa_admin_password '
+      - '"\"" not in ipa_admin_password '
+      - " \"'\" not in ipa_admin_password "
+    success_msg: "{{ success_msg_ipa_admin_pwd }}"
+    fail_msg: "{{ fail_msg_ipa_admin_pwd }}"
+  when: enable_security_support
+  tags: [ validate, security ]
 
 - name: Create ansible vault key
   set_fact:
     vault_key: "{{ lookup('password', '/dev/null chars=ascii_letters') }}"
   when: "'$ANSIBLE_VAULT;' not in config_content.stdout"
+  tags: init
 
 - name: Save vault key
   copy:
@@ -190,14 +263,17 @@
     force: yes
     mode: "{{ vault_file_perm }}"
   when: "'$ANSIBLE_VAULT;' not in config_content.stdout"
+  tags: init
 
 - name: Encrypt input config file
   command: >-
     ansible-vault encrypt {{ login_vars_filename }}
     --vault-password-file {{ vault_filename }}
   changed_when: false
+  tags: init
 
 - name: Update login_vars.yml permission
   file:
     path: "{{ login_vars_filename }}"
     mode: "{{ file_perm }}"
+  tags: init

+ 27 - 3
control_plane/roles/control_plane_common/tasks/verify_omnia_params.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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.
@@ -17,11 +17,13 @@
   stat:
     path: "{{ role_path }}/../../../{{ config_vaultname }}"
   register: vault_key_result
+  tags: init
 
 - name: Create ansible vault key if it does not exist
   set_fact:
     vault_key: "{{ lookup('password', '/dev/null chars=ascii_letters') }}"
   when: not vault_key_result.stat.exists
+  tags: init
 
 - name: Save vault key
   copy:
@@ -32,27 +34,32 @@
     force: yes
     mode: "{{ vault_file_perm }}"
   when: not vault_key_result.stat.exists
+  tags: init
 
 - name: Check if omnia config file is encrypted
   command: cat {{ role_path }}/../../../{{ config_filename }}
   changed_when: false
   register: config_content
   no_log: True
+  tags: init
 
 - name: Decrpyt omnia_config.yml
   command: >-
     ansible-vault decrypt {{ role_path }}/../../../{{ config_filename }}
     --vault-password-file {{ role_path }}/../../../{{ config_vaultname }}
   when: "'$ANSIBLE_VAULT;' in config_content.stdout"
+  tags: init
 
 - name: Include variable file omnia_config.yml
   include_vars: "{{ role_path }}/../../../{{ config_filename }}"
   no_log: True
+  tags: init
 
 - name: Validate input parameters are not empty
   fail:
     msg: "{{ input_omnia_failure_msg }}"
   register: input_config_check
+  tags: [ validate, templates ]
   when:
     - mariadb_password | length < 1 or
       k8s_version | length < 1 or
@@ -62,13 +69,15 @@
 - name: Validate login node parameters when login_node_reqd is set to true
   fail:
     msg: "{{ omnia_input_config_failure_msg }}"
+  tags: [ validate, templates ]
   when:
     - ( domain_name | length < 1 or
       realm_name | length < 1 or
       directory_manager_password | length < 1 or
       ipa_admin_password | length < 1 ) and
       ( login_node_required and
-      host_mapping_file )
+      host_mapping_file  and
+      not enable_security_support)
 
 - name: Assert mariadb_password
   assert:
@@ -81,18 +90,21 @@
         - " \"'\" not in mariadb_password "
     success_msg: "{{ success_msg_mariadb_password }}"
     fail_msg: "{{ fail_msg_mariadb_password }}"
+  tags: [ validate, templates ]
 
 - name: Assert kubernetes version
   assert:
     that: "('1.16.7' in k8s_version) or ('1.19.3' in k8s_version)"
     success_msg: "{{ success_msg_k8s_version }}"
     fail_msg: "{{ fail_msg_k8s_version }}"
+  tags: [ validate, templates ]
 
 - name: Assert kubernetes cni
   assert:
     that: "('calico' in k8s_cni) or ('flannel' in k8s_cni)"
     success_msg: "{{ success_msg_k8s_cni }}"
     fail_msg: "{{ fail_msg_k8s_cni }}"
+  tags: [ validate, templates ]
 
 - name: Save input variables from file
   set_fact:
@@ -102,6 +114,7 @@
     docker_username: "{{ docker_username }}"
     docker_password: "{{ docker_password }}"
   no_log: True
+  tags: init
 
 - name: Verify the value of login_node_required
   assert:
@@ -109,6 +122,7 @@
       - login_node_required == true or login_node_required == false
     success_msg: "{{ login_node_required_success_msg }}"
     fail_msg: "{{ login_node_required_fail_msg }}"
+  tags: [ validate, templates ]
 
 - name: Validate the domain name
   assert:
@@ -116,9 +130,11 @@
       - domain_name is regex("^(?!-)[A-Za-z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Za-z]{2,}$")
     success_msg: "{{ domain_name_success_msg }}"
     fail_msg: "{{ domain_name_fail_msg }}"
+  tags: [ validate, templates ]
   when:
     - host_mapping_file
     - login_node_required
+    - not enable_security_support
 
 - name: Validate the realm name
   assert:
@@ -127,9 +143,11 @@
       - '"." in realm_name'
     success_msg: "{{ realm_name_success_msg }}"
     fail_msg: "{{ realm_name_fail_msg }}"
+  tags: [ validate, templates ]
   when:
     - host_mapping_file
     - login_node_required
+    - not enable_security_support
 
 - name: Assert directory_manager_password
   assert:
@@ -142,9 +160,11 @@
       - " \"'\" not in directory_manager_password "
     success_msg: "{{ success_msg_directory_manager_password }}"
     fail_msg: "{{ fail_msg_directory_manager_password }}"
+  tags: [ validate, templates ]
   when:
     - host_mapping_file
-     - login_node_required
+    - login_node_required
+    - not enable_security_support
 
 - name: Assert ipa_admin_password
   assert:
@@ -157,17 +177,21 @@
       - " \"'\" not in ipa_admin_password "
     success_msg: "{{ success_msg_ipa_admin_password }}"
     fail_msg: "{{ fail_msg_ipa_admin_password }}"
+  tags: [ validate, templates ]
   when:
     - host_mapping_file
     - login_node_required
+    - not enable_security_support
 
 - name: Encrypt input config file
   command: >-
     ansible-vault encrypt {{ role_path }}/../../../{{ config_filename }}
     --vault-password-file {{ role_path }}/../../../{{ config_vaultname }}
   changed_when: false
+  tags: init
 
 - name: Update omnia_config.yml permission
   file:
     path: "{{ role_path }}/../../../{{ config_filename }}"
     mode: "{{ vault_file_perm }}"
+  tags: init

+ 51 - 3
control_plane/roles/control_plane_common/vars/main.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,9 +13,28 @@
 #  limitations under the License.
 ---
 
-# vars file for common
+# vars file for control_plane_common
 
 # Usage: package_installation.yml
+common_packages_leap:
+  - git
+  - gcc
+  - gcc-c++
+  - nodejs
+  - bzip2
+  - python2-pip
+  - python3-pip
+  - nano
+  - lvm2
+  - gettext
+  - net-tools
+  - python3-netaddr
+  - dos2unix
+  - cri-o
+  - make
+os_supported_leap: "leap"
+os_supported_leap_version: "15.3"
+python_version_leap: '3.6.15'
 common_packages:
   - epel-release
   - yum-utils
@@ -34,6 +53,7 @@ common_packages:
   - python3-netaddr
   - yum-plugin-versionlock
   - dos2unix
+  - make
 
 # Usage: pre_requisite.yml
 internet_delay: 0
@@ -51,23 +71,33 @@ selinux_status: "SElinux is not disabled. Disable it in /etc/sysconfig/selinux a
 ansible_python_version_status: "For CentOS 8.3, python bindings of firewalld, dnf, selinux are not available if python is installed from source and not from dnf. So please make sure python3.6 is installed using dnf. And ansible uses the python version 3.6 installed using dnf"
 python_version_support: '3.6.8'
 default_ansible_config_file_path: /etc/ansible/ansible.cfg
+invalid_run_tag_msg: "Failed. init tag should be used with run tags"
+invalid_skip_tag_msg: "Failed. init tag can't be used with skip tags"
 
-# Usage: password_config.yml
+# Usage: verify_login_inputs.yml
 login_vars_filename: "input_params/login_vars.yml"
 vault_filename: input_params/.login_vault_key
 min_length: 8
 max_length: 30
 min_username_length: 4
+min_length_grafana: 5
 file_perm: '0755'
 vault_file_perm: '0644'
+mount_dir_perm: '0775'
 nic_min_length: 3
 login_input_config_failure_msg: "Failed. Please provide all the required parameters in login_vars.yml"
 fail_msg_provision_password: "Failed. Incorrect provision_password format provided in login_vars.yml"
 fail_msg_cobbler_password: "Failed. Incorrect cobbler_password format provided in login_vars.yml file"
 fail_msg_idrac_credentials: "Failed. Incorrect idrac_username or idrac_password format provided in login_vars.yml"
+fail_msg_grafana_credentials: "Failed. Incorrect grafana_username or grafana_password format provided in login_vars.yml"
 fail_msg_ethernet_credentials: "Failed. Incorrect ethernet_switch_username or ethernet_switch_password format provided in login_vars.yml"
 fail_msg_ib_credentials: "Failed. Incorrect ib_username or ib_password format provided in login_vars.yml"
 fail_msg_me4_credentials: "Failed. Incorrect powervault_me4_username or powervault_me4_password format provided in login_vars.yml"
+login_security_config_failure_msg: "Failed. Please provide the required passwords in login_vars.yml for installing ipa"
+success_msg_dir_manager_password: "directory_manager_password successfully validated"
+fail_msg_dir_manager_password: "Failed. Incorrect format provided for directory_manager_password"
+success_msg_ipa_admin_pwd: "ipa_admin_password successfully validated"
+fail_msg_ipa_admin_pwd: "Failed. Incorrect format provided for ipa_admin_password"
 
 # Usage: verify_omnia_params.yml
 config_filename: "omnia_config.yml"
@@ -139,6 +169,8 @@ provision_os_success_msg: "provision_os validated"
 provision_os_fail_msg: "Failed. Incorrect provision_os selected. Supported OS are {{ os_supported_centos }} or {{ os_supported_rocky }}"
 provision_state_success_msg: "provision_state validated"
 provision_state_fail_msg: "Failed. Incorrect provision_state selected. Supported only stateful"
+enable_security_support_success_msg: "enable_security_support validated"
+enable_security_support_fail_msg: "Failed. enable_security_support only accepts boolean values true or false"
 
 # Usage: fetch_sm_inputs.yml
 ib_config_file: "{{ role_path }}/../../input_params/ib_vars.yml"
@@ -193,3 +225,19 @@ group_name_nfs: "nfs_node"
 # Usage: validate_device_mapping_file.yml
 fail_device_mapping_file_header: "Failed: Header (MAC,IP) should be present in the mapping file."
 device_mapping_header_format: "MAC,IP"
+
+# Usage: fetch_security_inputs.yml
+security_vars_filename: "input_params/security_vars.yml"
+input_security_failure_msg: "Please provide all the required parameters in security_vars.yml"
+dom_name_length: '63'
+dom_name_success_msg: "domain name successfully validated"
+dom_name_fail_msg: "Failed. Incorrect format provided for domain name in security_vars.yml"
+realm_success_msg: "realm_name successfully validated"
+realm_fail_msg: "Failed. Incorrect realm_name format in security_vars.yml"
+
+# Usage: validate_idrac_vars.yml
+idrac_input_filename: input_params/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"
+poweredge_model_success_msg: "poweredge_model validated"
+poweredge_model_fail_msg: "Failed. poweredge_model is incorrect or unsupported. Please update the list with the supported models in the correct format"

+ 84 - 0
control_plane/roles/control_plane_customiso/files/temp_leap15.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<!DOCTYPE profile>
+<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns">
+  <install>
+    <init>
+      <info_file>
+        <![CDATA[
+          textmode: 1]]>
+      </info_file>
+    </init>
+  </install>
+  <general>
+    <mode>
+      <confirm config:type="boolean">false</confirm>
+      <final_reboot config:type="boolean">true</final_reboot>
+    </mode>
+  </general>
+  <bootloader t="map">
+    <loader_type>default</loader_type>
+  </bootloader>
+  <host t="map">
+    <hosts t="list">
+      <hosts_entry t="map">
+        <host_address>127.0.0.1</host_address>
+        <names t="list">
+          <name>localhost</name>
+        </names>
+      </hosts_entry>
+    </hosts>
+  </host>
+  <networking t="map">
+    <dns t="map">
+      <dhcp_hostname t="boolean">false</dhcp_hostname>
+      <hostname>localhost.localdomain</hostname>
+      <resolv_conf_policy>auto</resolv_conf_policy>
+    </dns>
+  </networking>
+  <services-manager t="map">
+    <services t="map">
+      <enable t="list">
+        <service>chronyd</service>
+        <service>sshd</service>
+      </enable>
+    </services>
+  </services-manager>
+  <software t="map">
+    <install_recommended t="boolean">true</install_recommended>
+    <instsource/>
+    <packages t="list">
+      <package>openssh</package>
+      <package>firewalld</package>
+      <package>chrony</package>
+    </packages>
+  </software>
+  <ssh_import t="map">
+    <copy_config t="boolean">false</copy_config>
+    <import t="boolean">false</import>
+  </ssh_import>
+  <timezone t="map">
+    <timezone>ks_timezone</timezone>
+  </timezone>
+  <users t="list">
+    <user t="map">
+      <authorized_keys t="list"/>
+      <encrypted t="boolean">true</encrypted>
+      <fullname>root</fullname>
+      <gid>0</gid>
+      <home>/root</home>
+      <home_btrfs_subvolume t="boolean">false</home_btrfs_subvolume>
+      <password_settings t="map">
+        <expire/>
+        <flag/>
+        <inact/>
+        <max/>
+        <min/>
+        <warn/>
+      </password_settings>
+      <shell>/bin/bash</shell>
+      <uid>0</uid>
+      <user_password>ks_password</user_password>
+      <username>root</username>
+    </user>
+  </users>
+</profile>

+ 40 - 9
control_plane/roles/control_plane_customiso/tasks/check_prerequisites.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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,18 +13,35 @@
 # limitations under the License.
 ---
 
-- name: Install genisoimage package
+- name: Include control_plane_common vars
+  include_vars: ../../control_plane_common/vars/main.yml
+  tags: install
+
+- name: Include provision_cobbler vars
+  include_vars: ../../provision_cobbler/vars/main.yml
+  tags: install
+
+- name: Install xorriso package - rocky
   package:
-    name: genisoimage
+    name: "{{ iso_package }}"
     state: present
   tags: install
+  when:
+    - ansible_distribution | lower == os_supported_centos or
+      ansible_distribution | lower == os_supported_rocky
+
+- name: Install xorriso package - leap
+  zypper:
+    name: "{{ iso_package }}"
+    state: present
+  tags: install
+  when: os_supported_leap in ansible_distribution | lower
 
 - name: Install ansible-galaxy modules
   command: ansible-galaxy collection install {{ item }}
   changed_when: true
-  with_items:
-   - community.general
-   - dellemc.openmanage
+  tags: install
+  with_items: "{{ idrac_collections }}"
 
 - name: Install omsdk using pip
   pip:
@@ -34,14 +51,27 @@
 
 - name: Check iso mount folder
   stat:
-    path: "{{ iso_mount_path }}{{ isolinux_cfg_path }}"
+    path: "{{ iso_mount_path }}{{ grub_cfg_path }}"
   register: check_mount_iso
   tags: install
 
+- name: Include provision_cobbler vars
+  include_tasks: ../../provision_cobbler/tasks/mount_iso.yml
+  when: not check_mount_iso.stat.exists
+
+- name: Recheck iso mount folder
+  stat:
+    path: "{{ iso_mount_path }}{{ grub_cfg_path }}"
+  register: recheck_mount_iso
+  when: not check_mount_iso.stat.exists
+  tags: install
+
 - name: Incorrect iso mount
   fail:
     msg: "{{ iso_mount_check_fail_msg }}"
-  when: not check_mount_iso.stat.exists
+  when:
+    - not check_mount_iso.stat.exists
+    - not recheck_mount_iso.stat.exists
   register: iso_mount_fail
   tags: install
 
@@ -50,4 +80,5 @@
     path: "{{ role_path }}/../provision_idrac/files/{{ management_station_ip_file }}"
     line: "{{ mngmnt_network_ip }}"
     mode: "{{ file_permission }}"
-    create: yes
+    create: yes
+  tags: install

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

@@ -1,80 +0,0 @@
-#  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: ISO creation - centos
-  block:
-    - name: Create custom ISO
-      command: >-
-        mkisofs -o /tmp/{{ centos_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: centos_iso_status
-      tags: install
-      args:
-        chdir: "{{ tmp_iso_dir }}"
-
-    - name: Custom ISO creation status check
-      assert:
-        that:
-          - "'Total directory bytes:' in centos_iso_status.stderr"
-          - "'Path table size(bytes):' in centos_iso_status.stderr"
-          - "'Max brk space used' in centos_iso_status.stderr"
-          - "'extents written' in centos_iso_status.stderr"
-        success_msg: "{{ custom_iso_success_msg }}"
-        fail_msg: "{{ custom_iso_fail_msg }}"
-
-    - name: Copy ISO file to nfs share
-      copy:
-        src: "/tmp/{{ centos_iso_filename }}"
-        dest: "{{ nfs_share_offline_repo }}/{{ centos_iso_filename }}"
-        mode: preserve
-      tags: install
-  when: provision_os == os_supported_centos
-
-- name: ISO creation - rocky
-  block:
-    - name: Create custom ISO
-      command: >-
-        mkisofs -o /tmp/{{ rocky_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 "Rocky-8-4-x86_64-dvd"  {{ tmp_iso_dir }}
-      changed_when: true
-      register: rocky_iso_status
-      tags: install
-      args:
-        chdir: "{{ tmp_iso_dir }}"
-
-    - name: Custom ISO creation status check
-      assert:
-        that:
-          - "'Total directory bytes:' in rocky_iso_status.stderr"
-          - "'Path table size(bytes):' in rocky_iso_status.stderr"
-          - "'Max brk space used' in rocky_iso_status.stderr"
-          - "'extents written' in rocky_iso_status.stderr"
-        success_msg: "{{ custom_iso_success_msg }}"
-        fail_msg: "{{ custom_iso_fail_msg }}"
-
-    - name: Copy ISO file to nfs share
-      copy:
-        src: "/tmp/{{ rocky_iso_filename }}"
-        dest: "{{ nfs_share_offline_repo }}/{{ rocky_iso_filename }}"
-        mode: preserve
-      tags: install
-  when: provision_os == os_supported_rocky
-
-- name: Remove the kickstart file
-  file:
-    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    state: absent
-  tags: install

+ 39 - 0
control_plane/roles/control_plane_customiso/tasks/create_unattended_iso_centos.yml

@@ -0,0 +1,39 @@
+#  Copyright 2022 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 centos
+  command: >-
+    xorriso -as mkisofs -o {{ nfs_share_offline_repo }}/{{ centos_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: centos_iso_status
+  tags: install
+  args:
+    chdir: "{{ tmp_iso_dir }}"
+
+- name: Custom ISO creation status check centos
+  assert:
+    that:
+      - custom_iso_success_keyword1 in centos_iso_status.stderr
+      - custom_iso_success_keyword2 in centos_iso_status.stderr
+    success_msg: "{{ custom_iso_success_msg }}"
+    fail_msg: "{{ custom_iso_fail_msg }}"
+  tags: install
+
+- name: Remove the kickstart file
+  file:
+    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+    state: absent
+  tags: install

+ 39 - 0
control_plane/roles/control_plane_customiso/tasks/create_unattended_iso_leap.yml

@@ -0,0 +1,39 @@
+#  Copyright 2022 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 leap
+  command: >-
+    xorriso -as mkisofs -no-emul-boot -boot-load-size 4 -boot-info-table -iso-level 4 -b boot/x86_64/loader/isolinux.bin 
+    -c boot/x86_64/loader/boot.cat -eltorito-alt-boot -e boot/x86_64/efi -no-emul-boot -o {{ nfs_share_offline_repo }}/{{ leap_iso_filename }} {{ tmp_iso_dir }}
+  changed_when: true
+  register: leap_iso_status
+  tags: install
+  args:
+    chdir: "{{ tmp_iso_dir }}"
+
+- name: Custom ISO creation status check leap
+  assert:
+    that:
+      - custom_iso_success_keyword1 in leap_iso_status.stderr
+      - custom_iso_success_keyword2 in leap_iso_status.stderr
+    success_msg: "{{ custom_iso_success_msg }}"
+    fail_msg: "{{ custom_iso_fail_msg }}"
+  tags: install
+  
+- name: Remove the kickstart file
+  file:
+    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+    state: absent
+  tags: install

+ 44 - 0
control_plane/roles/control_plane_customiso/tasks/create_unattended_iso_rocky.yml

@@ -0,0 +1,44 @@
+#  Copyright 2022 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: Fetch rocky profile name
+  shell: set -o pipefail && grep 'Rocky-8' {{ tmp_iso_dir }}{{ grub_cfg_path }} | head -1
+  register: rocky_profile_name
+  changed_when: false
+
+- name: Create custom ISO rocky
+  command: >-
+    xorriso -as mkisofs -o {{ nfs_share_offline_repo }}/{{ rocky_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 {{ rocky_profile_name.stdout.split(' ')[4] | replace("'","") }}  {{ tmp_iso_dir }}
+  changed_when: true
+  register: rocky_iso_status
+  tags: install
+  args:
+    chdir: "{{ tmp_iso_dir }}"
+
+- name: Custom ISO creation status check rocky
+  assert:
+    that:
+      - custom_iso_success_keyword1 in rocky_iso_status.stderr
+      - custom_iso_success_keyword2 in rocky_iso_status.stderr
+    success_msg: "{{ custom_iso_success_msg }}"
+    fail_msg: "{{ custom_iso_fail_msg }}"
+  tags: install
+
+- name: Remove the kickstart file
+  file:
+    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+    state: absent
+  tags: install

+ 175 - 113
control_plane/roles/control_plane_customiso/tasks/edit_iso_config.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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,71 +13,6 @@
 #  limitations under the License.
 ---
 
-- name: Include control_plane_common vars
-  include_vars: ../../control_plane_common/vars/main.yml
-
-- name: Include provision_cobbler vars
-  include_vars: ../../provision_cobbler/vars/main.yml
-
-- name: Copy files to tmp folder
-  command: cp -r {{ iso_mount_path }} /tmp/
-  changed_when: true
-  tags: install
-
-- name: Set centos kickstart file name
-  set_fact:
-    idrac_kickstart_file: "{{ idrac_centos_ks }}"
-  when: provision_os == os_supported_centos
-
-- name: Set rocky kickstart file name
-  set_fact:
-    idrac_kickstart_file: "{{ idrac_rocky_ks }}"
-  when: provision_os == os_supported_rocky
-
-- 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:/{{ idrac_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: "timeout=60", replace: "timeout=5" }
-    - { regexp: "kernel /images/pxeboot/vmlinuz", replace: "kernel /images/pxeboot/vmlinuz ks=cdrom:/{{ idrac_kickstart_file }}" }
-    - { regexp: "linuxefi /images/pxeboot/vmlinuz", replace: "linuxefi /images/pxeboot/vmlinuz ks=cdrom:/{{ idrac_kickstart_file }}" }
-    - { regexp: "rd.live.check quiet", replace: "" }
-  tags: install
-
-- name: Remove the kickstart file if exists
-  file:
-    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    state: absent
-  tags: install
-
-- name: Create the centos kickstart file
-  copy:
-    src: "{{ role_path }}/files/temp_centos7.cfg"
-    dest: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    mode: "{{ file_permission }}"
-  tags: install
-  when: provision_os == os_supported_centos
-  
-- name: Create the rocky kickstart file
-  copy:
-    src: "{{ role_path }}/files/temp_rocky8.cfg"
-    dest: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    mode: "{{ file_permission }}"
-  tags: install
-  when: provision_os == os_supported_rocky
-
 - name: Random phrase generation
   command: openssl rand -base64 12
   changed_when: false
@@ -92,54 +27,181 @@
   register: encrypt_login_pass
   tags: install
 
-- name: Configure kickstart file - Password
-  replace:
-    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    regexp: '^rootpw --iscrypted ks_password'
-    replace: 'rootpw --iscrypted {{ encrypt_login_pass.stdout }}'
-  no_log: true
-  tags: install
-
-- name: Configure kickstart file centos - nic
-  lineinfile:
-    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    insertafter: '^network  --bootproto=dhcp --device=link --onboot=on --activate'
-    line: 'network  --bootproto=dhcp --device={{ item }} --onboot=on --activate'
-  tags: install
-  with_items: "{{ centos_host_nic }}"
-  when: provision_os == os_supported_centos
-
-- name: Configure kickstart file rocky - nic
-  lineinfile:
-    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    insertafter: '^network  --bootproto=dhcp --device=link --onboot=on --activate'
-    line: 'network  --bootproto=dhcp --device={{ item }} --onboot=on --activate'
-  tags: install
-  with_items: "{{ rocky_host_nic }}"
-  when: provision_os == os_supported_rocky
-
-- name: Configure kickstart file - timezone
-  replace:
-    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    regexp: '^timezone --utc ks_timezone'
-    replace: 'timezone --utc {{ timezone }}'
-  tags: install
-
-- name: Configure kickstart file - language
-  replace:
-    path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    regexp: '^lang ks_language'
-    replace: 'lang {{ language }}'
+- name: Create a tmp iso directory
+  file:
+    path: "{{ tmp_iso_dir }}"
+    state: directory
+    mode: "{{ file_permission }}"
   tags: install
 
-- name: Copy kickstart file to iso mount path
-  copy:
-    src: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
-    dest: "{{ tmp_iso_dir }}{{ idrac_kickstart_file }}"
-    mode: preserve
+- name: Copy files to tmp folder
+  command:  rsync -AHPSXav {{ iso_mount_path }} {{ tmp_iso_dir }}
+  changed_when: true
+  args:
+    warn: false
   tags: install
 
-- name: Remove ^M characters
-  command: dos2unix {{ tmp_iso_dir }}{{ idrac_kickstart_file }}
-  changed_when: false
-  failed_when: false
+- name: Kickstart file changes rocky and centos
+  block:
+    - name: Kickstart file changes centos
+      block:
+        - name: Set centos kickstart file name
+          set_fact:
+            idrac_kickstart_file: "{{ idrac_centos_ks }}"
+          tags: install
+
+        - name: Remove the kickstart file if exists
+          file:
+            path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+            state: absent
+          tags: install
+
+        - name: Create the centos kickstart file
+          copy:
+            src: "{{ role_path }}/files/temp_centos7.cfg"
+            dest: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+            mode: "{{ file_permission }}"
+          tags: install
+
+        - name: Configure kickstart file centos - nic
+          lineinfile:
+            path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+            insertafter: '^network  --bootproto=dhcp --device=link --onboot=on --activate'
+            line: 'network  --bootproto=dhcp --device={{ item }} --onboot=on --activate'
+          tags: install
+          with_items: "{{ centos_host_nic }}"
+      when: provision_os == os_supported_centos
+
+    - name: Kickstart file changes rocky
+      block:
+        - name: Set rocky kickstart file name
+          set_fact:
+            idrac_kickstart_file: "{{ idrac_rocky_ks }}"
+          tags: install
+
+        - name: Remove the kickstart file if exists
+          file:
+            path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+            state: absent
+          tags: install
+
+        - name: Create the rocky kickstart file
+          copy:
+            src: "{{ role_path }}/files/temp_rocky8.cfg"
+            dest: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+            mode: "{{ file_permission }}"
+          tags: install
+
+        - name: Configure kickstart file rocky - nic
+          lineinfile:
+            path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+            insertafter: '^network  --bootproto=dhcp --device=link --onboot=on --activate'
+            line: 'network  --bootproto=dhcp --device={{ item }} --onboot=on --activate'
+          tags: install
+          with_items: "{{ rocky_host_nic }}"
+      when: provision_os == os_supported_rocky
+
+    - name: Configure kickstart file - Password
+      replace:
+        path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        regexp: '^rootpw --iscrypted ks_password'
+        replace: 'rootpw --iscrypted {{ encrypt_login_pass.stdout }}'
+      no_log: true
+      tags: install
+
+    - name: Configure kickstart file - timezone
+      replace:
+        path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        regexp: '^timezone --utc ks_timezone'
+        replace: 'timezone --utc {{ timezone }}'
+      tags: install
+
+    - name: Configure kickstart file - language
+      replace:
+        path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        regexp: '^lang ks_language'
+        replace: 'lang {{ language }}'
+      tags: install
+
+    - name: Copy kickstart file to iso mount path
+      copy:
+        src: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        dest: "{{ tmp_iso_dir }}{{ idrac_kickstart_file }}"
+        mode: preserve
+      tags: install
+
+    - name: Remove ^M characters
+      command: dos2unix {{ tmp_iso_dir }}{{ idrac_kickstart_file }}
+      changed_when: false
+      failed_when: false
+
+    - 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:/{{ idrac_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: "timeout=60", replace: "timeout=5" }
+        - { regexp: "kernel /images/pxeboot/vmlinuz", replace: "kernel /images/pxeboot/vmlinuz ks=cdrom:/{{ idrac_kickstart_file }}" }
+        - { regexp: "linuxefi /images/pxeboot/vmlinuz", replace: "linuxefi /images/pxeboot/vmlinuz ks=cdrom:/{{ idrac_kickstart_file }}" }
+        - { regexp: "rd.live.check quiet", replace: "" }
+      tags: install
+  when:
+    - provision_os == os_supported_rocky or
+      provision_os == os_supported_centos
+
+- name: Kickstart file changes leap
+  block:
+    - name: Set leap kickstart file name
+      set_fact:
+        idrac_kickstart_file: "{{ idrac_leap_ks }}"
+      tags: install
+  
+    - name: Create the leap kickstart file
+      copy:
+        src: "{{ role_path }}/files/temp_leap15.xml"
+        dest: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        mode: "{{ file_permission }}"
+      tags: install
+
+    - name: Configure kickstart file - Password
+      replace:
+        path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        regexp: '      <user_password>ks_password</user_password>'
+        replace: '      <user_password>{{ encrypt_login_pass.stdout }}</user_password>'
+      no_log: true
+      tags: install
+
+    - name: Configure kickstart file - timezone
+      replace:
+        path: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        regexp: '    <timezone>ks_timezone</timezone>'
+        replace: '    <timezone>{{ timezone }}</timezone>'
+      tags: install
+
+    - name: Copy kickstart file to iso mount path
+      copy:
+        src: "{{ role_path }}/files/{{ idrac_kickstart_file }}"
+        dest: "/tmp/leap/{{ idrac_kickstart_file }}"
+        mode: preserve
+      tags: install
+
+    - name: Edit grub.cfg
+      replace:
+        path: "{{ tmp_iso_dir }}{{ grub_cfg_path }}"
+        regexp: "{{ item.regexp }}"
+        replace: "{{ item.replace }}"
+      with_items:
+        - { regexp: "  timeout=60", replace: "  timeout=5" }
+      tags: install
+  when: provision_os == os_supported_leap

+ 12 - 3
control_plane/roles/control_plane_customiso/tasks/main.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -21,5 +21,14 @@
 - name: Edit iso config files
   include_tasks: edit_iso_config.yml
 
-- name: Create unattended iso file
-  include_tasks: create_unattended_iso.yml
+- name: Create unattended iso file rocky
+  include_tasks: create_unattended_iso_rocky.yml
+  when: provision_os == os_supported_rocky
+
+- name: Create unattended iso file leap
+  include_tasks: create_unattended_iso_leap.yml
+  when: provision_os == os_supported_leap
+
+- name: Create unattended iso file centos
+  include_tasks: create_unattended_iso_centos.yml
+  when: provision_os == os_supported_centos

+ 22 - 10
control_plane/roles/control_plane_customiso/vars/main.yml

@@ -1,4 +1,4 @@
-# Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2022 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,21 +15,33 @@
 
 # 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 {{ provision_os }} ISO file."
+# Usage: check_prerequisites.yml
+iso_mount_path: /mnt/{{ provision_os }}/
+iso_mount_check_fail_msg: "ISO file not mounted successfully. Ensure /mnt/{{ provision_os }} path is mounted with {{ provision_os }} ISO file."
+management_station_ip_file: "management_station_ip.txt"
+idrac_collections:
+  - community.general
+  - dellemc.openmanage
+iso_package: xorriso
 
-#Usage: edit_iso_config.yml
-tmp_iso_dir: /tmp/iso/
+# Usage: edit_iso_config.yml
+tmp_iso_dir: /tmp/{{ provision_os }}/
 idrac_centos_ks: centos7.cfg
 idrac_rocky_ks: rocky8.cfg
+idrac_leap_ks: autoinst.xml
 file_permission: 0744
 isolinux_cfg_path: isolinux/isolinux.cfg
 grub_cfg_path: EFI/BOOT/grub.cfg
 
-#Usage: create_unattended_iso.yml
-centos_iso_filename: unattended_centos7.iso
+# Usage: create_unattended_iso_rocky.yml
 rocky_iso_filename: unattended_rocky8.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."
-management_station_ip_file: "management_station_ip.txt"
+custom_iso_fail_msg: "Unattended ISO file creation failed. Ensure /mnt/{{ provision_os }} path is mounted with valid {{ provision_os }} ISO file."
+custom_iso_success_keyword1: "ISO image produced:"
+custom_iso_success_keyword2: "completed successfully"
+
+# Usage: create_unattended_iso_leap.yml
+leap_iso_filename: unattended_leap15.iso
+
+# Usage: create_unattended_iso_centos.yml
+centos_iso_filename: unattended_centos7.iso

+ 9 - 26
control_plane/roles/control_plane_device/files/Dockerfile

@@ -1,35 +1,18 @@
 # Dockerfile for creating the management network container
+FROM alpine:latest
 
-FROM centos:8
-
-# RPM REPOs
-RUN dnf install -y \
-    epel-release \
-    && dnf clean all \
-    && rm -rf /var/cache/dnf
-
-RUN dnf install -y dhcp-server
-RUN dnf install -y python3-netaddr
-
-RUN yum install -y \
-  ansible \
-  cronie \
-  tftp\
-  tftp-server\
-  xinetd \
-  net-tools \
-  && yum clean all \
-  &&  rm -rf /var/cache/yum
+#Installing packages
+RUN apk add dhcp
+RUN apk add ansible
+RUN apk add openrc
 
+#Creation of directories and files
 RUN mkdir /root/omnia
+RUN mkdir /etc/periodic/5min
+RUN touch /var/lib/dhcp/dhcpd.leases
 
 #Copy Configuration files
 COPY dhcpd.conf  /etc/dhcp/dhcpd.conf
-COPY tftp /etc/xinetd.d/tftp
 COPY inventory_creation.yml /root/
 COPY mngmnt_container_configure.yml /root/
-
-RUN systemctl enable tftp
-RUN systemctl enable dhcpd
-
-CMD ["sbin/init"]
+COPY cron_inv /etc/periodic/5min

+ 2 - 0
control_plane/roles/control_plane_device/files/cron_inv

@@ -0,0 +1,2 @@
+#!/bin/sh
+ansible-playbook /root/inventory_creation.yml

+ 12 - 3
control_plane/roles/control_plane_device/files/inventory_creation.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -19,7 +19,7 @@
   tasks:
     - name: Read dhcp file
       set_fact:
-        var: "{{ lookup('file', '/var/lib/dhcpd/dhcpd.leases').split()| unique | select| list }}"
+        var: "{{ lookup('file', '/var/lib/dhcp/dhcpd.leases').split()| unique | select| list }}"
 
     - name: Filter the ip
       set_fact:
@@ -43,6 +43,7 @@
 
     - name: Temp result
       shell: cat /root/omnia/control_plane/roles/collect_device_info/files/mgmt_provisioned_hosts.yml |sort|uniq
+      changed_when: false
       register: inventory
 
     - name: Final Inventory
@@ -50,4 +51,12 @@
 
     - name: New line at end of file
       shell: echo "">> omnia/control_plane/roles/collect_device_info/files/mgmt_provisioned_hosts.yml
-      changed_when: false
+      changed_when: false
+
+    - name: Delete files
+      file:
+        path: "{{ item }}"
+        state: absent
+      with_items:
+        - "/root/temp.txt"
+        -  "/root/dynamic_hosts.yml"

+ 6 - 3
control_plane/roles/control_plane_device/files/k8s_mngmnt_network.yml

@@ -27,10 +27,13 @@ spec:
         - name: mngmnt-network-container
           image: 'localhost/mngmnt_network_container:latest'
           imagePullPolicy: Never
-          command:
-            - /sbin/init
+          command: ["sh", "-c", "tail -f /dev/null"]
           volumeMounts:
             - name: omnia-storage
               mountPath: /root/omnia
           securityContext:
-            privileged: true
+            allowPrivilegeEscalation: true
+            capabilities:
+              add:
+                - NET_RAW
+            privileged: false

+ 19 - 56
control_plane/roles/control_plane_device/files/mngmnt_container_configure.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -18,64 +18,27 @@
   connection: local
   gather_facts: false
   tasks:
-  - name: Change mode of tftpboot
-    file:
-      path: /var/lib/tftpboot
-      mode: 0777
-
-  - name: Link for tftp services
-    shell: cp -v /usr/lib/systemd/system/tftp.service /etc/systemd/system/tftp-server.service
-
-  - name: Link for tftp services
-    shell: cp -v /usr/lib/systemd/system/tftp.socket /etc/systemd/system/tftp-server.socket
-
-  - name: Edit the tftp-server service file
-    replace:
-      path: /etc/systemd/system/tftp-server.service
-      regexp: ^Requires=tftp.socket
-      replace: Requires=tftp-server.socket
-
-  - name: Edit the tftp-server service file
-    replace:
-      path: /etc/systemd/system/tftp-server.service
-      regexp: ^ExecStart=/usr/sbin/in.tftpd -s /var/lib/tftpboot
-      replace: ExecStart=/usr/sbin/in.tftpd -c -p -s /var/lib/tftpboot
-
-  - name: Edit the tftp-server service file
-    replace:
-      path: /etc/systemd/system/tftp-server.service
-      regexp: ^Also=tftp.socket
-      replace: Also=tftp.socket
+  - name: Enable DHCP
+    command: dhcpd {{ mngmnt_nic }}
+    changed_when: false
 
-  - name: Edit the tftp-server service file
-    lineinfile:
-      path: /etc/systemd/system/tftp-server.service
-      insertafter: '^[Install]'
-      line: 'WantedBy=multi-user.target'
+  - name: Start cron
+    command: crond
+    changed_when: false
 
-  - name: Edit the tftp-server socket file
-    lineinfile:
-      path: /etc/systemd/system/tftp-server.socket
-      line: "BindIPv6Only=both"
-      insertafter: [Socket]
+  - name: Add log file for cron jobs
+    command: crond -L /var/log/cron_jobs
+    changed_when: false
 
-  - name: Start tftp services
-    service:
-      name: tftp-server
-      state: started
+  - name: Add cron job for 5 min
+    shell: echo "*/5    *       *       *       *       run-parts /etc/periodic/5min" >> /var/spool/cron/crontabs/root
+    changed_when: false
 
-  - name: Start dhcpd services
-    service:
-      name: dhcpd
-      state: started
+  - name: Install python-netaddr
+    package:
+      name: py3-netaddr
+      state: present
 
-  - name: Fetch ansible-playbook location
-    command: whereis ansible-playbook
+  - name: Change permissions
+    command: chmod a+x /etc/periodic/5min/cron_inv
     changed_when: false
-    register: ansible_playbook_location
-
-  - name: Add inventory cron job
-    cron:
-      name: Create inventory
-      minute: "*/5"
-      job: "{{ ansible_playbook_location.stdout.split(' ')[1] }} /root/inventory_creation.yml"

+ 0 - 20
control_plane/roles/control_plane_device/files/tftp

@@ -1,20 +0,0 @@
-# default: off
-# description: The tftp server serves files using the trivial file transfer \
-#       protocol.  The tftp protocol is often used to boot diskless \
-#       workstations, download configuration files to network-aware printers, \
-#       and to start the installation process for some operating systems.
-service tftp
-{
-        socket_type             = dgram
-        protocol                = udp
-        wait                    = yes
-        user                    = root
-        server                  = /usr/sbin/in.tftpd
-        server_args             = -s /var/lib/tftpboot
-        disable                 = no
-        per_source              = 11
-        cps                     = 100 2
-        flags                   = IPv4
-}
-
-

+ 2 - 2
control_plane/roles/control_plane_device/tasks/configure_mngmnt_network_container.yml

@@ -32,7 +32,7 @@
 
 - name: Configuring mngmnt_network container
   command: 'kubectl exec --stdin --tty -n network-config {{ mngmnt_network_pod_name.stdout }} \
-    -- ansible-playbook /root/mngmnt_container_configure.yml'
+    -- ansible-playbook /root/mngmnt_container_configure.yml -e mngmnt_nic="{{ mngmnt_network_nic }}"'
   changed_when: false
   tags: install
   when: not mngmnt_network_container_status
@@ -43,4 +43,4 @@
     state: absent
   with_items:
     - "{{ role_path }}/files/dhcpd.conf"
-    - "{{ role_path }}/files/temp_mgmt_mapping_file.csv.bak"
+    - "{{ role_path }}/files/temp_mgmt_mapping_file.csv.bak"

+ 7 - 19
control_plane/roles/control_plane_ib/files/Dockerfile

@@ -1,26 +1,14 @@
 # Dockerfile for creating the management network container
+FROM alpine:latest
 
-FROM centos:8
-
-# RPM REPOs
-RUN dnf install -y \
-    epel-release \
-    && dnf clean all \
-    && rm -rf /var/cache/dnf
-
-RUN dnf install dhcp-server -y
-RUN yum install -y \
-  ansible \
-  cronie \
-  net-tools \
-  && yum clean all \
-  &&  rm -rf /var/cache/yum
+#Installation of packages
+RUN apk add dhcp
+RUN apk add ansible
+RUN apk add openrc
 
+#Creation of directories and files
 RUN mkdir /root/omnia
+RUN touch /var/lib/dhcp/dhcpd.leases
 
 #Copy Configuration files
 COPY dhcpd.conf  /etc/dhcp/dhcpd.conf
-
-RUN systemctl enable dhcpd
-
-CMD ["sbin/init"]

+ 5 - 5
control_plane/roles/control_plane_ib/files/infiniband_container_configure.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -18,7 +18,7 @@
   connection: local
   gather_facts: false
   tasks:
-  - name: Start dhcpd services
-    service:
-      name: dhcpd
-      state: started
+  - name: Install netaddr
+    package:
+      name: py3-netaddr
+      state: present

+ 6 - 3
control_plane/roles/control_plane_ib/files/k8s_infiniband.yml

@@ -27,10 +27,13 @@ spec:
         - name: infiniband-container
           image: 'localhost/infiniband-container:latest'
           imagePullPolicy: Never
-          command:
-            - /sbin/init
+          command: ["sh", "-c", "tail -f /dev/null"]
           volumeMounts:
             - name: omnia-storage
               mountPath: /root/omnia
           securityContext:
-            privileged: true
+            allowPrivilegeEscalation: true
+            capabilities:
+              add:
+                - NET_RAW
+            privileged: false

+ 4 - 5
control_plane/roles/control_plane_k8s/tasks/k8s_init.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -16,7 +16,6 @@
 - name: Disable SWAP (1/2)
   command: /usr/sbin/swapoff -a
   changed_when: true
-  tags: init
 
 - name: Disable SWAP in fstab (2/2)
   replace:
@@ -52,7 +51,7 @@
 - name: Initialize kubeadm (This process may take 5-10min)
   block:
     - name: Initialize kubeadm (This process may take 5-10min)
-      command: "/bin/kubeadm init --pod-network-cidr='{{ appliance_k8s_pod_net_cidr }}' \
+      command: "kubeadm init --pod-network-cidr='{{ appliance_k8s_pod_net_cidr }}' \
         --apiserver-advertise-address='{{ ansible_default_ipv4.address }}'"
       changed_when: true
       register: init_output
@@ -62,7 +61,7 @@
       changed_when: true
 
     - name: Initialize kubeadm (This process may take 5-10min)
-      command: "/bin/kubeadm init --pod-network-cidr='{{ appliance_k8s_pod_net_cidr }}' \
+      command: "kubeadm init --pod-network-cidr='{{ appliance_k8s_pod_net_cidr }}' \
           --apiserver-advertise-address='{{ ansible_default_ipv4.address }}'"
       changed_when: true
       register: init_output
@@ -136,4 +135,4 @@
 - name: Edge / Workstation Install allows pods to schedule on manager
   command: kubectl taint nodes --all node-role.kubernetes.io/master-
   changed_when: true
-  failed_when: false
+  failed_when: false

+ 4 - 5
control_plane/roles/control_plane_k8s/tasks/k8s_installation.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -112,9 +112,8 @@
   when: docker_username and docker_password
   register: docker_repo
   until: docker_repo is not failed
-  retries: 20
-  delay: 10
-  tags: install
+  retries: "{{ max_retries }}"
+  delay: "{{ min_delay }}"
 
 - name: Install docker-ce-cli
   package:
@@ -137,4 +136,4 @@
 
 - name: Wait for 30sec for kubelet to get things ready
   pause:
-    seconds: 30
+    seconds: "{{ wait_time }}"

+ 187 - 0
control_plane/roles/control_plane_k8s/tasks/k8s_installation_leap.yml

@@ -0,0 +1,187 @@
+#  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: Permanently Disable swap
+  mount:
+    name: "swap"
+    fstype: swap
+    state: absent
+
+- name: Copy k8s.conf file
+  copy:
+    src: k8s.conf
+    dest: "{{ k8s_conf_dest }}"
+    owner: root
+    group: root
+    mode: "{{ conf_file_mode }}"
+
+- name: Copy crio.conf file
+  copy:
+    src: crio.conf
+    dest: "{{ crio_conf_dest }}"
+    owner: root
+    group: root
+    mode: "{{ conf_file_mode }}"
+
+- name: Enable the kernel modules overlay and br_netfilter
+  modprobe:
+    name: "{{ item }}"
+    state: present
+  with_items:
+    - overlay
+    - br_netfilter
+
+- name: Update sysctl to handle incorrectly routed traffic when iptables is bypassed
+  copy:
+    src: k8s-crio.conf
+    dest: "{{ k8s_crio_conf_dest }}"
+    owner: root
+    group: root
+    mode: "{{ conf_file_mode }}"
+
+- name: Update sysctl
+  command: /sbin/sysctl --system
+  changed_when: true
+
+- name: Installing cri-o
+  zypper:
+    name: cri-o
+    state: present
+  changed_when: true
+
+- name: Start and enable crio
+  service:
+    name: crio
+    state: restarted
+    daemon_reload: yes
+    enabled: yes
+  register: crio_repo_result
+  until: crio_repo_result is not failed
+  retries: "{{ min_retries }}"
+
+- name: Add kubernetes repo
+  zypper_repository:
+     name: google-k8s
+     repo: "{{ k8s_repo_leap }}"
+     state: present
+     autorefresh: yes
+
+- name: Import rpm-package key for installing kubernetes
+  rpm_key:
+    key: "{{ rpm_pkg_leap }}"
+    state: present
+
+- name: Import yum key for installing kubernetes
+  rpm_key:
+    key: "{{ yum_key_leap }}"
+    state: present
+
+- name: Import gpg-pubkey key for installing kubernetes
+  command: "{{ gpg_pubkey_leap }}"
+  args:
+    warn: false
+  changed_when: false
+
+- name: Refresh repositories and installing conntrack-tools
+  zypper:
+    name: conntrack-tools
+    state: present
+    update_cache: yes
+
+- name: Expect-package installation
+  pip:
+   name: pexpect
+   state: present
+   executable: pip3
+
+- name: Install Kubeadm
+  ansible.builtin.expect:
+    command: zypper install --oldpackage "{{ kubeadm_version }}"
+    responses:
+        (.*) [1/2/c/d/?](.): '2'
+        (.*)(y): 'y'
+
+- name: Install Kubelet
+  ansible.builtin.expect:
+    command: zypper install --oldpackage "{{ kubelet_version }}"
+    responses:
+        (.*) [1/2/c/d/?](.): '2'
+        (.*)(y): 'y'
+
+- name: Install Kubectl
+  zypper:
+     name: "{{ kubectl_version }}"
+     state: present
+     oldpackage: yes
+     force: yes
+
+- name: Install common packages
+  zypper:
+    name: "{{ common_pkgs_leap }}"
+    state: present
+
+- name: Versionlocking kubeadm
+  command: zypper addlock "{{ kubeadm_version }}"
+  args:
+    warn: false
+  changed_when: false
+
+- name: Versionlocking kubectl
+  command: zypper addlock "{{ kubelet_version }}"
+  args:
+    warn: false
+  changed_when: false
+
+- name: Versionlocking kubelet
+  command: zypper addlock "{{ kubectl_version }}"
+  args:
+    warn: false
+  changed_when: false
+
+- name: Add docker community edition repository for docker-ce-cli
+  get_url:
+    url: "{{ docker_repo_url_leap }}"
+    dest: "{{ docker_repo_dest_leap }}"
+  when: docker_username and docker_password
+  register: docker_repo
+  until: docker_repo is not failed
+  retries: "{{ max_retries }}"
+  delay: "{{ min_delay }}"
+  tags: install
+
+- name: Install docker-compose
+  zypper:
+    name: docker-compose
+    state: present
+  when: docker_username and docker_password
+
+- name: Start and enable crio
+  service:
+    name: crio
+    state: restarted
+    daemon_reload: yes
+    enabled: yes
+  register: crio_repo_result
+  until: crio_repo_result is not failed
+  retries: "{{ min_retries }}"
+
+- name: Start and enable kubernetes - kubelet
+  service:
+    name: kubelet
+    state: restarted
+    enabled: yes
+
+- name: Wait for 30sec for kubelet to get things ready
+  pause:
+    seconds: "{{ wait_time }}"

+ 10 - 3
control_plane/roles/control_plane_k8s/tasks/main.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,7 +14,14 @@
 ---
 
 - name: Install K8s packages
-  import_tasks: k8s_installation.yml
+  include_tasks: k8s_installation.yml
+  when:
+    - ( mgmt_os == os_supported_centos ) and ( ansible_distribution_version >= os_supported_centos_version ) or
+      ( mgmt_os == os_supported_rocky ) and ( ansible_distribution_version >= os_supported_rocky_version )
+
+- name: Install K8s packages for leap
+  include_tasks: k8s_installation_leap.yml
+  when: ( os_supported_leap in mgmt_os ) and ( ansible_distribution_version >= os_supported_leap_version )
 
 - name: Configure firewalld
   import_tasks: k8s_firewalld.yml
@@ -26,4 +33,4 @@
   import_tasks: k8s_init.yml
 
 - name: Deploy K8s dashboard
-  import_tasks: k8s_services.yml
+  import_tasks: k8s_services.yml

+ 22 - 1
control_plane/roles/control_plane_k8s/vars/main.yml

@@ -15,6 +15,27 @@
 
 # vars file for kubernetes
 
+# Usage: k8s_installation_leap.yml
+k8s_repo_leap: https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
+rpm_pkg_leap: https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
+yum_key_leap:  https://packages.cloud.google.com/yum/doc/yum-key.gpg
+gpg_pubkey_leap: "rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}'"
+docker_repo_url_leap: https://download.docker.com/linux/sles/docker-ce.repo
+docker_repo_dest_leap: /etc/YaST2/docker-ce.repo
+kubeadm_version: kubeadm-1.21.0-0.x86_64
+kubelet_version: kubelet-1.21.0-0.x86_64
+kubectl_version: kubectl-1.21.0-0.x86_64
+common_pkgs_leap:
+  - openssl
+  - bash-completion
+  - buildah
+os_supported_leap: "leap"
+os_supported_leap_version: "15.3"
+min_retries: 3
+max_retries: 3
+min_delay: 10
+wait_time: 30
+ 
 # Usage: k8s_installation.yml
 common_packages:
   - openssl
@@ -98,4 +119,4 @@ metallb_run_as_user_port: "65534"
 k8s_dashboard_yaml_url: https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml
 k8s_dashboard_admin_file_dest: /root/k8s/k8s_dashboard_admin.yaml
 k8s_dashboard_admin_file_mode: 0655
-nfs_path: /var/nfs_awx
+nfs_path: /var/nfs_awx

File diff suppressed because it is too large
+ 1363 - 0
control_plane/roles/control_plane_monitoring/files/CoreDNS.json


+ 3 - 0
control_plane/roles/control_plane_monitoring/files/Dockerfile_promtail

@@ -0,0 +1,3 @@
+FROM docker.io/grafana/promtail:2.4.1
+
+COPY promtail_config.yml /etc/promtail/config.yml

File diff suppressed because it is too large
+ 1527 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_API_server.json


File diff suppressed because it is too large
+ 2266 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Cluster.json


File diff suppressed because it is too large
+ 2039 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Namespace_Pods.json


+ 918 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Node_Pods.json

@@ -0,0 +1,918 @@
+{
+  "__inputs": [],
+  "__elements": [],
+  "__requires": [
+    {
+      "type": "grafana",
+      "id": "grafana",
+      "name": "Grafana",
+      "version": "8.3.2"
+    },
+    {
+      "type": "panel",
+      "id": "graph",
+      "name": "Graph (old)",
+      "version": ""
+    },
+    {
+      "type": "datasource",
+      "id": "prometheus",
+      "name": "Prometheus",
+      "version": "1.0.0"
+    },
+    {
+      "type": "panel",
+      "id": "table-old",
+      "name": "Table (old)",
+      "version": ""
+    }
+  ],
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "fiscalYearStartMonth": 0,
+  "graphTooltip": 0,
+  "id": null,
+  "iteration": 1640151600624,
+  "links": [],
+  "liveNow": false,
+  "panels": [
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 5,
+      "panels": [],
+      "title": "CPU Usage",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 10,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 1
+      },
+      "hiddenSeries": false,
+      "id": 1,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 0,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": true,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{pod}}",
+          "refId": "A",
+          "step": 10
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "CPU Usage",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": false
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 8
+      },
+      "id": 6,
+      "panels": [],
+      "title": "CPU Quota",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "columns": [],
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 9
+      },
+      "id": 2,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "styles": [
+        {
+          "alias": "Time",
+          "align": "auto",
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "Time",
+          "type": "hidden"
+        },
+        {
+          "alias": "CPU Usage",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #A",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        },
+        {
+          "alias": "CPU Requests",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #B",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        },
+        {
+          "alias": "CPU Requests %",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #C",
+          "thresholds": [],
+          "type": "number",
+          "unit": "percentunit"
+        },
+        {
+          "alias": "CPU Limits",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #D",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        },
+        {
+          "alias": "CPU Limits %",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #E",
+          "thresholds": [],
+          "type": "number",
+          "unit": "percentunit"
+        },
+        {
+          "alias": "Pod",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "pod",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        },
+        {
+          "alias": "",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "pattern": "/.*/",
+          "thresholds": [],
+          "type": "string",
+          "unit": "short"
+        }
+      ],
+      "targets": [
+        {
+          "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A",
+          "step": 10
+        },
+        {
+          "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "B",
+          "step": 10
+        },
+        {
+          "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "C",
+          "step": 10
+        },
+        {
+          "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "D",
+          "step": 10
+        },
+        {
+          "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "E",
+          "step": 10
+        }
+      ],
+      "thresholds": [],
+      "title": "CPU Quota",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "transform": "table",
+      "type": "table-old",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": false
+        }
+      ]
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 16
+      },
+      "id": 7,
+      "panels": [],
+      "title": "Memory Usage",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 10,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 17
+      },
+      "hiddenSeries": false,
+      "id": 3,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 0,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": true,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\", container!=\"\"}) by (pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{pod}}",
+          "refId": "A",
+          "step": 10
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Memory Usage (w/o cache)",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "bytes",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": false
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 24
+      },
+      "id": 8,
+      "panels": [],
+      "title": "Memory Quota",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "columns": [],
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 25
+      },
+      "id": 4,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "styles": [
+        {
+          "alias": "Time",
+          "align": "auto",
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "Time",
+          "type": "hidden"
+        },
+        {
+          "alias": "Memory Usage",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #A",
+          "thresholds": [],
+          "type": "number",
+          "unit": "bytes"
+        },
+        {
+          "alias": "Memory Requests",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #B",
+          "thresholds": [],
+          "type": "number",
+          "unit": "bytes"
+        },
+        {
+          "alias": "Memory Requests %",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #C",
+          "thresholds": [],
+          "type": "number",
+          "unit": "percentunit"
+        },
+        {
+          "alias": "Memory Limits",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #D",
+          "thresholds": [],
+          "type": "number",
+          "unit": "bytes"
+        },
+        {
+          "alias": "Memory Limits %",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #E",
+          "thresholds": [],
+          "type": "number",
+          "unit": "percentunit"
+        },
+        {
+          "alias": "Memory Usage (RSS)",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #F",
+          "thresholds": [],
+          "type": "number",
+          "unit": "bytes"
+        },
+        {
+          "alias": "Memory Usage (Cache)",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #G",
+          "thresholds": [],
+          "type": "number",
+          "unit": "bytes"
+        },
+        {
+          "alias": "Memory Usage (Swap)",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "Value #H",
+          "thresholds": [],
+          "type": "number",
+          "unit": "bytes"
+        },
+        {
+          "alias": "Pod",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "link": false,
+          "linkTargetBlank": false,
+          "linkTooltip": "Drill down",
+          "linkUrl": "",
+          "pattern": "pod",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        },
+        {
+          "alias": "",
+          "align": "auto",
+          "colors": [],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "pattern": "/.*/",
+          "thresholds": [],
+          "type": "string",
+          "unit": "short"
+        }
+      ],
+      "targets": [
+        {
+          "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A",
+          "step": 10
+        },
+        {
+          "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "B",
+          "step": 10
+        },
+        {
+          "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod) / sum(kube_pod_container_resource_requests_memory_bytes{node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "C",
+          "step": 10
+        },
+        {
+          "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "D",
+          "step": 10
+        },
+        {
+          "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod) / sum(kube_pod_container_resource_limits_memory_bytes{node=~\"$node\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "E",
+          "step": 10
+        },
+        {
+          "expr": "sum(node_namespace_pod_container:container_memory_rss{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "F",
+          "step": 10
+        },
+        {
+          "expr": "sum(node_namespace_pod_container:container_memory_cache{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "G",
+          "step": 10
+        },
+        {
+          "expr": "sum(node_namespace_pod_container:container_memory_swap{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)",
+          "format": "table",
+          "instant": true,
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "H",
+          "step": 10
+        }
+      ],
+      "thresholds": [],
+      "title": "Memory Quota",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "transform": "table",
+      "type": "table-old",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": false
+        }
+      ]
+    }
+  ],
+  "refresh": "10s",
+  "schemaVersion": 33,
+  "style": "dark",
+  "tags": [
+    "kubernetes-mixin"
+  ],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": true,
+          "text": "default",
+          "value": "default"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "multi": false,
+        "name": "datasource",
+        "options": [],
+        "query": "prometheus",
+        "queryValue": "",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "uid": "$datasource"
+        },
+        "definition": "",
+        "hide": 2,
+        "includeAll": false,
+        "multi": false,
+        "name": "cluster",
+        "options": [],
+        "query": {
+          "query": "label_values(kube_pod_info, cluster)",
+          "refId": "Prometheus-cluster-Variable-Query"
+        },
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "tagValuesQuery": "",
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "current": {},
+        "datasource": {
+          "uid": "$datasource"
+        },
+        "definition": "",
+        "hide": 0,
+        "includeAll": false,
+        "multi": true,
+        "name": "node",
+        "options": [],
+        "query": {
+          "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, node)",
+          "refId": "Prometheus-node-Variable-Query"
+        },
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "tagValuesQuery": "",
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      }
+    ]
+  },
+  "time": {
+    "from": "now-1h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "UTC",
+  "title": "Kubernetes / Compute Resources / Node (Pods)",
+  "uid": "200ac8fdbfbb74b39aff88118e4d1c2c",
+  "version": 1,
+  "weekStart": ""
+}

File diff suppressed because it is too large
+ 1638 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Pod.json


File diff suppressed because it is too large
+ 1850 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Compute_Resources_Workload.json


File diff suppressed because it is too large
+ 2071 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Kubelet.json


File diff suppressed because it is too large
+ 1615 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Cluster.json


File diff suppressed because it is too large
+ 1297 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Namespace_Pods.json


File diff suppressed because it is too large
+ 1492 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Namespace_Workload.json


File diff suppressed because it is too large
+ 1085 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Pod.json


File diff suppressed because it is too large
+ 1226 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Networking_Workload.json


+ 963 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_Scheduler.json

@@ -0,0 +1,963 @@
+{
+  "__inputs": [],
+  "__elements": [],
+  "__requires": [
+    {
+      "type": "grafana",
+      "id": "grafana",
+      "name": "Grafana",
+      "version": "8.3.2"
+    },
+    {
+      "type": "panel",
+      "id": "graph",
+      "name": "Graph (old)",
+      "version": ""
+    },
+    {
+      "type": "datasource",
+      "id": "prometheus",
+      "name": "Prometheus",
+      "version": "1.0.0"
+    },
+    {
+      "type": "panel",
+      "id": "stat",
+      "name": "Stat",
+      "version": ""
+    }
+  ],
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": false,
+  "fiscalYearStartMonth": 0,
+  "graphTooltip": 0,
+  "id": null,
+  "iteration": 1640159989547,
+  "links": [],
+  "liveNow": false,
+  "panels": [
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "N/A"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 0,
+        "y": 0
+      },
+      "id": 2,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "min"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "sum(up{job=\"kube-scheduler\"})",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "Up",
+      "type": "stat"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 10,
+        "x": 4,
+        "y": 0
+      },
+      "hiddenSeries": false,
+      "id": 3,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": true,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum(rate(scheduler_e2e_scheduling_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} e2e",
+          "refId": "A"
+        },
+        {
+          "expr": "sum(rate(scheduler_binding_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} binding",
+          "refId": "B"
+        },
+        {
+          "expr": "sum(rate(scheduler_scheduling_algorithm_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} scheduling algorithm",
+          "refId": "C"
+        },
+        {
+          "expr": "sum(rate(scheduler_volume_scheduling_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} volume",
+          "refId": "D"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Scheduling Rate",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "ops",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "ops",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 10,
+        "x": 14,
+        "y": 0
+      },
+      "hiddenSeries": false,
+      "id": 4,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": true,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} e2e",
+          "refId": "A"
+        },
+        {
+          "expr": "histogram_quantile(0.99, sum(rate(scheduler_binding_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} binding",
+          "refId": "B"
+        },
+        {
+          "expr": "histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} scheduling algorithm",
+          "refId": "C"
+        },
+        {
+          "expr": "histogram_quantile(0.99, sum(rate(scheduler_volume_scheduling_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}} volume",
+          "refId": "D"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Scheduling latency 99th Quantile",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "s",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "s",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 0,
+        "y": 7
+      },
+      "hiddenSeries": false,
+      "id": 5,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"2..\"}[5m]))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "2xx",
+          "refId": "A"
+        },
+        {
+          "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"3..\"}[5m]))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "3xx",
+          "refId": "B"
+        },
+        {
+          "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"4..\"}[5m]))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "4xx",
+          "refId": "C"
+        },
+        {
+          "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"5..\"}[5m]))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "5xx",
+          "refId": "D"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Kube API Request Rate",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "ops",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "ops",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 16,
+        "x": 8,
+        "y": 7
+      },
+      "hiddenSeries": false,
+      "id": 6,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-scheduler\", instance=~\"$instance\", verb=\"POST\"}[5m])) by (verb, url, le))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{verb}} {{url}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Post Request Latency 99th Quantile",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "s",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "s",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 14
+      },
+      "hiddenSeries": false,
+      "id": 7,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": true,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-scheduler\", instance=~\"$instance\", verb=\"GET\"}[5m])) by (verb, url, le))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{verb}} {{url}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Get Request Latency 99th Quantile",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "s",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "s",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 0,
+        "y": 21
+      },
+      "hiddenSeries": false,
+      "id": 8,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "process_resident_memory_bytes{job=\"kube-scheduler\", instance=~\"$instance\"}",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Memory",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "bytes",
+          "logBase": 1,
+          "show": true
+        },
+        {
+          "format": "bytes",
+          "logBase": 1,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 8,
+        "y": 21
+      },
+      "hiddenSeries": false,
+      "id": 9,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "rate(process_cpu_seconds_total{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "CPU usage",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "bytes",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "bytes",
+          "logBase": 1,
+          "min": 0,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 16,
+        "y": 21
+      },
+      "hiddenSeries": false,
+      "id": 10,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "go_goroutines{job=\"kube-scheduler\",instance=~\"$instance\"}",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Goroutines",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    }
+  ],
+  "refresh": "10s",
+  "schemaVersion": 33,
+  "style": "dark",
+  "tags": [
+    "kubernetes-mixin"
+  ],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": false,
+          "text": "default",
+          "value": "default"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "multi": false,
+        "name": "datasource",
+        "options": [],
+        "query": "prometheus",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "uid": "$datasource"
+        },
+        "definition": "",
+        "hide": 0,
+        "includeAll": true,
+        "multi": false,
+        "name": "instance",
+        "options": [],
+        "query": {
+          "query": "label_values(process_cpu_seconds_total{job=\"kube-scheduler\"}, instance)",
+          "refId": "Prometheus-instance-Variable-Query"
+        },
+        "refresh": 2,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "tagValuesQuery": "",
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      }
+    ]
+  },
+  "time": {
+    "from": "now-1h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "UTC",
+  "title": "Kubernetes / Scheduler",
+  "uid": "2e6b6a3b4bddf1427b3a55aa1311c656",
+  "version": 1,
+  "weekStart": ""
+}

+ 820 - 0
control_plane/roles/control_plane_monitoring/files/Kubernetes_StatefulSets.json

@@ -0,0 +1,820 @@
+{
+  "__inputs": [],
+  "__elements": [],
+  "__requires": [
+    {
+      "type": "grafana",
+      "id": "grafana",
+      "name": "Grafana",
+      "version": "8.3.2"
+    },
+    {
+      "type": "panel",
+      "id": "graph",
+      "name": "Graph (old)",
+      "version": ""
+    },
+    {
+      "type": "datasource",
+      "id": "prometheus",
+      "name": "Prometheus",
+      "version": "1.0.0"
+    },
+    {
+      "type": "panel",
+      "id": "stat",
+      "name": "Stat",
+      "version": ""
+    }
+  ],
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": false,
+  "fiscalYearStartMonth": 0,
+  "graphTooltip": 0,
+  "id": null,
+  "iteration": 1640160026561,
+  "links": [],
+  "liveNow": false,
+  "panels": [
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "fixedColor": "rgb(31, 120, 193)",
+            "mode": "fixed"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "0"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 0,
+        "y": 0
+      },
+      "id": 2,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "sum(rate(container_cpu_usage_seconds_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$statefulset.*\"}[3m]))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "CPU",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "fixedColor": "rgb(31, 120, 193)",
+            "mode": "fixed"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "0"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 8,
+        "y": 0
+      },
+      "id": 3,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "sum(container_memory_usage_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$statefulset.*\"}) / 1024^3",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "Memory",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "fixedColor": "rgb(31, 120, 193)",
+            "mode": "fixed"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "0"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 16,
+        "y": 0
+      },
+      "id": 4,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$statefulset.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\",pod=~\"$statefulset.*\"}[3m]))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "Network",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "0"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 0,
+        "y": 7
+      },
+      "id": 5,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "max(kube_statefulset_replicas{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "Desired Replicas",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "0"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 6,
+        "y": 7
+      },
+      "id": 6,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "min(kube_statefulset_status_replicas_current{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "Replicas of current version",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "0"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 12,
+        "y": 7
+      },
+      "id": 7,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "max(kube_statefulset_status_observed_generation{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "Observed Generation",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [
+            {
+              "options": {
+                "match": "null",
+                "result": {
+                  "text": "0"
+                }
+              },
+              "type": "special"
+            }
+          ],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 7
+      },
+      "id": 8,
+      "links": [],
+      "maxDataPoints": 100,
+      "options": {
+        "colorMode": "none",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "expr": "max(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A"
+        }
+      ],
+      "title": "Metadata Generation",
+      "type": "stat"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": {
+        "uid": "$datasource"
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 0,
+        "y": 10
+      },
+      "hiddenSeries": false,
+      "id": 9,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "8.3.2",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "max(kube_statefulset_replicas{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "replicas specified",
+          "refId": "A"
+        },
+        {
+          "expr": "max(kube_statefulset_status_replicas{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "replicas created",
+          "refId": "B"
+        },
+        {
+          "expr": "min(kube_statefulset_status_replicas_ready{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "ready",
+          "refId": "C"
+        },
+        {
+          "expr": "min(kube_statefulset_status_replicas_current{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "replicas of current version",
+          "refId": "D"
+        },
+        {
+          "expr": "min(kube_statefulset_status_replicas_updated{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "updated",
+          "refId": "E"
+        }
+      ],
+      "thresholds": [],
+      "timeRegions": [],
+      "title": "Replicas",
+      "tooltip": {
+        "shared": false,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "mode": "time",
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false
+      }
+    }
+  ],
+  "refresh": "",
+  "schemaVersion": 33,
+  "style": "dark",
+  "tags": [
+    "kubernetes-mixin"
+  ],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": false,
+          "text": "default",
+          "value": "default"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "multi": false,
+        "name": "datasource",
+        "options": [],
+        "query": "prometheus",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "uid": "$datasource"
+        },
+        "definition": "",
+        "hide": 2,
+        "includeAll": false,
+        "label": "cluster",
+        "multi": false,
+        "name": "cluster",
+        "options": [],
+        "query": {
+          "query": "label_values(kube_statefulset_metadata_generation, cluster)",
+          "refId": "Prometheus-cluster-Variable-Query"
+        },
+        "refresh": 2,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "tagValuesQuery": "",
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "current": {},
+        "datasource": {
+          "uid": "$datasource"
+        },
+        "definition": "",
+        "hide": 0,
+        "includeAll": false,
+        "label": "Namespace",
+        "multi": false,
+        "name": "namespace",
+        "options": [],
+        "query": {
+          "query": "label_values(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", cluster=\"$cluster\"}, namespace)",
+          "refId": "Prometheus-namespace-Variable-Query"
+        },
+        "refresh": 2,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "tagValuesQuery": "",
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "current": {},
+        "datasource": {
+          "uid": "$datasource"
+        },
+        "definition": "",
+        "hide": 0,
+        "includeAll": false,
+        "label": "Name",
+        "multi": false,
+        "name": "statefulset",
+        "options": [],
+        "query": {
+          "query": "label_values(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\"}, statefulset)",
+          "refId": "Prometheus-statefulset-Variable-Query"
+        },
+        "refresh": 2,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "tagValuesQuery": "",
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      }
+    ]
+  },
+  "time": {
+    "from": "now-1h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "UTC",
+  "title": "Kubernetes / StatefulSets",
+  "uid": "a31c1f46e6f727cb37c0d731a7245005",
+  "version": 1,
+  "weekStart": ""
+}

File diff suppressed because it is too large
+ 1163 - 0
control_plane/roles/control_plane_monitoring/files/Prometheus_Overview.json


+ 135 - 0
control_plane/roles/control_plane_monitoring/files/loki_dashboard.json

@@ -0,0 +1,135 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "id": 1,
+  "links": [],
+  "panels": [
+    {
+      "datasource": "control-plane-loki",
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 4,
+      "options": {
+        "dedupStrategy": "none",
+        "enableLogDetails": true,
+        "prettifyLogMessage": false,
+        "showCommonLabels": false,
+        "showLabels": false,
+        "showTime": false,
+        "sortOrder": "Descending",
+        "wrapLogMessage": false
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "loki",
+            "uid": "control-plane-loki"
+          },
+          "expr": "{filename=\"/var/log/omnia.log\",job=\"Omnia\"}",
+          "queryType": "randomWalk",
+          "refId": "A"
+        }
+      ],
+      "title": "omnia.log",
+      "type": "logs"
+    },
+    {
+      "datasource": "control-plane-loki",
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 8
+      },
+      "id": 2,
+      "options": {
+        "dedupStrategy": "none",
+        "enableLogDetails": true,
+        "prettifyLogMessage": false,
+        "showCommonLabels": false,
+        "showLabels": false,
+        "showTime": false,
+        "sortOrder": "Descending",
+        "wrapLogMessage": false
+      },
+      "pluginVersion": "8.3.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "loki",
+            "uid": "control-plane-loki"
+          },
+          "expr": "{filename=\"/var/log/messages\",job=\"syslog\"}",
+          "queryType": "randomWalk",
+          "refId": "A"
+        }
+      ],
+      "title": "syslog",
+      "type": "logs"
+    }
+  ],
+  "schemaVersion": 30,
+  "style": "dark",
+  "tags": [],
+  "templating": {
+    "list": []
+  },
+  "time": {
+    "from": "now-6h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "",
+  "title": "loki",
+  "uid": "1k9NY90nz",
+  "version": 1
+}

+ 138 - 0
control_plane/roles/control_plane_monitoring/files/promtail_config.yml

@@ -0,0 +1,138 @@
+server:
+  http_listen_port: 9080
+  grpc_listen_port: 0
+
+positions:
+  filename: /tmp/positions.yaml
+
+clients:
+  - url: http://localhost:3100/loki/api/v1/push
+
+scrape_configs:
+- job_name: varlogs
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: varlogs
+      __path__: /var/log/*log
+
+- job_name: Directory Server Utilization
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: Directory Server Utilization
+      __path__: /var/log/dirsrv/slapd-OMNIA-TEST/access
+
+- job_name: Directory Server Errors
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: Directory Server Errors
+      __path__: /var/log/dirsrv/slapd-OMNIA-TEST/errors
+
+- job_name: PKI Transactions
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: PKI Transactions
+      __path__: /var/log/pki/pki-tomcat/ca/transactions
+
+- job_name: KDC Utilization
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: KDC Utilization
+      __path__: /var/log/krb5kdc.log
+
+- job_name: FreeIPA API Call
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: FreeIPA API Call
+      __path__: /var/log/httpd/*
+
+- job_name: audit
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: audit
+      __path__: /var/log/audit/*log
+
+- job_name: SSSD
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: SSSD
+      __path__: /var/log/sssd/*log
+
+- job_name: secure
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: secure
+      __path__: /var/log/secure
+
+- job_name: Omnia
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: Omnia
+      __path__: /var/log/omnia.log
+
+- job_name: syslog
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: syslog
+      __path__: /var/log/messages
+
+- job_name: cron
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: cron
+      __path__: /var/log/cron
+
+- job_name: IPA Server and Client
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: IPA Server and Client
+      __path__: /var/log/ipa*log
+
+- job_name: Package Rocky
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: Package Rocky
+      __path__: /var/log/dnf.log
+
+- job_name: Package Leap
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: Package Leap
+      __path__: /var/log/zypper.log
+
+- job_name: k8s pods
+  static_configs:
+  - targets:
+      - localhost
+    labels:
+      job: k8s pods
+      __path__: /var/log/pods/*/*/*log

+ 59 - 0
control_plane/roles/control_plane_monitoring/tasks/configure_k8s_prom_grafana.yml

@@ -0,0 +1,59 @@
+#  Copyright 2022 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: Get kube-prometheus svc IP
+  command: kubectl get svc -n {{ monitoring_namespace }} -l app=kube-prometheus-stack-prometheus -o=jsonpath='{.items[0].spec.clusterIP}'
+  changed_when: false
+  register: kube_prom_svc_ip
+
+- name: Get kube-prometheus svc port
+  command: kubectl get svc -n {{ monitoring_namespace }} -l app=kube-prometheus-stack-prometheus -o=jsonpath='{.items[0].spec.ports[0].port}'
+  changed_when: false
+  register: kube_prom_svc_port
+
+- name: Create prometheus datasource in grafana
+  community.grafana.grafana_datasource:
+    name: control-plane-prometheus
+    grafana_url: "http://{{ grafana_svc_ip.stdout }}:{{ grafana_svc_port.stdout }}"
+    grafana_user: "{{ grafana_username }}"
+    grafana_password: "{{ grafana_password }}"
+    ds_type: prometheus
+    ds_url: "http://{{ kube_prom_svc_ip.stdout }}:{{ kube_prom_svc_port.stdout }}"
+    access: proxy
+  no_log: true
+
+- name: Import K8s grafana dashboards
+  community.grafana.grafana_dashboard:
+    grafana_url: "http://{{ grafana_svc_ip.stdout }}:{{ grafana_svc_port.stdout }}"
+    grafana_user: "{{ grafana_username }}"
+    grafana_password: "{{ grafana_password }}"
+    state: present
+    commit_message: Updated by ansible
+    overwrite: yes
+    path: "{{ role_path }}/files/{{ item }}"
+  with_items: "{{ grafana_dashboard_json_files }}"
+  no_log: true
+
+- name: Save grafana svc ip
+  replace:
+    path: "{{ role_path }}/../../../roles/k8s_start_services/files/grafana_svc_details.ini"
+    regexp: "ip=.*"
+    replace: "ip={{ grafana_svc_ip.stdout }}"
+
+- name: Save grafana port
+  replace:
+    path: "{{ role_path }}/../../../roles/k8s_start_services/files/grafana_svc_details.ini"
+    regexp: "port=.*"
+    replace: "port={{ grafana_svc_port.stdout }}"

+ 49 - 0
control_plane/roles/control_plane_monitoring/tasks/configure_loki_grafana.yml

@@ -0,0 +1,49 @@
+#  Copyright 2022 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: Wait for loki pod to come to ready state
+  command: kubectl wait --for=condition=ready --timeout=10m -n "{{ grafana_namespace }}" pod -l app="{{ loki_k8s_name }}"
+  changed_when: false
+
+- name: Get loki service ip
+  command: kubectl get svc loki -n {{ grafana_namespace }} -o=jsonpath='{.spec.clusterIP}'
+  changed_when: false
+  register: loki_svc_ip
+
+- name: Get loki service port
+  command: kubectl get svc loki -n {{ grafana_namespace }} -o=jsonpath='{.spec.ports[0].port}'
+  changed_when: false
+  register: loki_svc_port
+
+- name: Create loki datasource in grafana
+  community.grafana.grafana_datasource:
+    name: control-plane-loki
+    grafana_url: "http://{{ grafana_svc_ip.stdout }}:{{ grafana_svc_port.stdout }}"
+    grafana_user: "{{ grafana_username }}"
+    grafana_password: "{{ grafana_password }}"
+    ds_type: loki
+    ds_url: "http://{{ loki_svc_ip.stdout }}:{{ loki_svc_port.stdout }}"
+  no_log: true
+
+- name: Import loki dashboard in grafana
+  community.grafana.grafana_dashboard:
+    grafana_url: "http://{{ grafana_svc_ip.stdout }}:{{ grafana_svc_port.stdout }}"
+    grafana_user: "{{ grafana_username }}"
+    grafana_password: "{{ grafana_password }}"
+    state: present
+    commit_message: Updated by ansible
+    overwrite: yes
+    path: "{{ role_path }}/files/loki_dashboard.json"
+  no_log: true

+ 63 - 0
control_plane/roles/control_plane_monitoring/tasks/install_k8s_prom_stack.yml

@@ -0,0 +1,63 @@
+#  Copyright 2022 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 prometheus-community chart
+  kubernetes.core.helm_repository:
+    name: prometheus-community
+    repo_url: "{{ helm_repo_prometheus }}"
+  failed_when: False
+
+- name: Install kube-prom-stack
+  block:
+    - name: Install kube-prom-stack
+      kubernetes.core.helm:
+        name: "{{ monitoring_app_name }}"
+        chart_ref: prometheus-community/kube-prometheus-stack
+        chart_version: "{{ k8s_prom_stack_chart_version }}"
+        update_repo_cache: True
+        release_namespace: "{{ monitoring_namespace }}"
+        create_namespace : yes
+        wait: true
+        values:
+          grafana:
+            enabled: False
+  rescue:
+    - name: Delete helm kube-prom-stack deployments
+      command: helm delete {{ monitoring_app_name }} -n {{ monitoring_namespace }}
+      changed_when: True
+      failed_when: False
+
+    - name: Delete existing kube-prom-stack crd
+      command: "kubectl delete crd {{ item }}"
+      changed_when: True
+      failed_when: False
+      with_items: "{{ k8s_prom_stack_crd }}"
+
+    - name: Install kube-prom-stack
+      kubernetes.core.helm:
+        name: "{{ monitoring_app_name }}"
+        chart_ref: prometheus-community/kube-prometheus-stack
+        chart_version: "{{ k8s_prom_stack_chart_version }}"
+        update_repo_cache: True
+        release_namespace: "{{ monitoring_namespace }}"
+        create_namespace : yes
+        wait: true
+        values:
+          grafana:
+            enabled: False
+
+- name: Wait for kube-prom-stack pod to come to ready state
+  command: kubectl wait --for=condition=ready --timeout=10m -n "{{ monitoring_namespace }}" pod -l app=kube-prometheus-stack-operator
+  changed_when: false

+ 63 - 0
control_plane/roles/control_plane_monitoring/tasks/k8s_loki_pod.yml

@@ -0,0 +1,63 @@
+#  Copyright 2022 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: Deploy loki pod
+  kubernetes.core.k8s:
+    state: present
+    definition:
+      apiVersion: apps/v1
+      kind: Deployment
+      metadata:
+          name: "{{ loki_k8s_name }}"
+          namespace: "{{ grafana_namespace }}"
+          labels:
+              app: "{{ loki_k8s_name }}"
+      spec:
+          selector:
+              matchLabels:
+                  app: "{{ loki_k8s_name }}"
+          replicas: 1
+          strategy:
+              type: RollingUpdate
+          template:
+              metadata:
+                  labels:
+                      app: "{{ loki_k8s_name }}"
+              spec:
+                  volumes:
+                    - name: varlog
+                      hostPath:
+                        path: /var/log
+                        type: Directory
+
+                  hostAliases:
+                    - ip: "127.0.0.1"
+                      hostnames:
+                        - "loki"
+                        - "promtail"
+
+                  containers:
+                    - name: loki
+                      image: docker.io/grafana/loki:2.4.1
+                      imagePullPolicy: "Always"
+                      ports:
+                        - containerPort: "{{ loki_port }}"
+
+                    - name: promtail
+                      image: localhost/promtail:latest
+                      imagePullPolicy: "Never"
+                      volumeMounts:
+                        - name: varlog
+                          mountPath: /var/log

+ 33 - 0
control_plane/roles/control_plane_monitoring/tasks/loki_service.yml

@@ -0,0 +1,33 @@
+#  Copyright 2022 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: Service for loki
+  kubernetes.core.k8s:
+    state: present
+    definition:
+      apiVersion: v1
+      kind: Service
+      metadata:
+        name: "{{ loki_k8s_name }}"
+        namespace: "{{ grafana_namespace }}"
+        labels:
+          app: "{{ loki_k8s_name }}"
+      spec:
+        type: ClusterIP
+        ports:
+          - name: loki
+            port: "{{ loki_port }}"
+        selector:
+          app: "{{ loki_k8s_name }}"

+ 32 - 0
control_plane/roles/control_plane_monitoring/tasks/main.yml

@@ -0,0 +1,32 @@
+#  Copyright 2022 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 K8s prometheus stack
+  import_tasks: install_k8s_prom_stack.yml
+
+- name: Configure K8s prometheus in grafana
+  import_tasks: configure_k8s_prom_grafana.yml
+
+- name: Build promtail image
+  import_tasks: promtail_image.yml
+
+- name: Deploy loki pod
+  import_tasks: k8s_loki_pod.yml
+
+- name: Deploy loki service
+  import_tasks: loki_service.yml
+
+- name: Configure loki in grafana
+  import_tasks: configure_loki_grafana.yml

+ 27 - 0
control_plane/roles/control_plane_monitoring/tasks/promtail_image.yml

@@ -0,0 +1,27 @@
+#  Copyright 2022 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: Update realm_name in promtail_config.yml
+  replace:
+    path: "{{ role_path }}/files/promtail_config.yml"
+    regexp: 'OMNIA-TEST'
+    replace: "{{ realm_name | replace('.','-') }}"
+  when: enable_security_support
+
+- name: Promtail image creation
+  command: "buildah bud -f Dockerfile_promtail -t {{ promtail_image_name }}:{{ promtail_image_tag }} ."
+  changed_when: true
+  args:
+    chdir: "{{ role_path }}/files/"

+ 56 - 0
control_plane/roles/control_plane_monitoring/vars/main.yml

@@ -0,0 +1,56 @@
+#  Copyright 2022 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.
+---
+
+# Usage: install_k8s_prom_stack.yml
+helm_repo_prometheus: https://prometheus-community.github.io/helm-charts
+monitoring_namespace: monitoring
+monitoring_app_name: monitoring
+k8s_prom_stack_chart_version: 25.0.0
+k8s_prom_stack_crd:
+  - alertmanagerconfigs.monitoring.coreos.com
+  - alertmanagers.monitoring.coreos.com
+  - podmonitors.monitoring.coreos.com
+  - probes.monitoring.coreos.com
+  - prometheuses.monitoring.coreos.com
+  - prometheusrules.monitoring.coreos.com
+  - servicemonitors.monitoring.coreos.com
+  - thanosrulers.monitoring.coreos.com
+
+# Usage: configure_k8s_prom_grafana.yml
+grafana_namespace: grafana
+grafana_dashboard_json_files:
+  - CoreDNS.json
+  - Kubernetes_API_server.json
+  - Kubernetes_Compute_Resources_Cluster.json
+  - Kubernetes_Compute_Resources_Namespace_Pods.json
+  - Kubernetes_Compute_Resources_Node_Pods.json
+  - Kubernetes_Compute_Resources_Pod.json
+  - Kubernetes_Compute_Resources_Workload.json
+  - Kubernetes_Kubelet.json
+  - Kubernetes_Networking_Cluster.json
+  - Kubernetes_Networking_Namespace_Pods.json
+  - Kubernetes_Networking_Namespace_Workload.json
+  - Kubernetes_Networking_Pod.json
+  - Kubernetes_Networking_Workload.json
+  - Kubernetes_Scheduler.json
+  - Prometheus_Overview.json
+
+# Usage: promtail_image.yml
+promtail_image_name: "promtail"
+promtail_image_tag: "latest"
+
+# Usage: k8s_loki_pod.yml
+loki_k8s_name: loki
+loki_port: 3100

+ 1 - 1
control_plane/roles/control_plane_repo/tasks/download_fmw_updates.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.

+ 1 - 1
control_plane/roles/control_plane_repo/tasks/install_dsu.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.

+ 8 - 11
control_plane/roles/control_plane_repo/tasks/main.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,16 +13,13 @@
 #  limitations under the License.
 ---
 
-- name: Include common variables
-  include_vars:  ../../control_plane_common/vars/main.yml
+- block:
+    - name: Include common variables
+      include_vars:  ../../control_plane_common/vars/main.yml
 
-- name: Validate idrac_vars
-  include_tasks: validate_idrac_vars.yml
+    - name: Install DSU
+      include_tasks: install_dsu.yml
 
-- name: Install DSU
-  include_tasks: install_dsu.yml
+    - name: Download iDRAC firmware updates
+      include_tasks: download_fmw_updates.yml
   when: firmware_update_required
-
-- name: Download iDRAC firmware updates
-  include_tasks: download_fmw_updates.yml
-  when: firmware_update_required

+ 3 - 10
control_plane/roles/control_plane_repo/vars/main.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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,18 +13,11 @@
 #  limitations under the License.
 ---
 
-# vars file for offline_repo
-
-# Usage: validate_idrac_vars.yml
-idrac_input_filename: input_params/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"
-poweredge_model_success_msg: "poweredge_model validated"
-poweredge_model_fail_msg: "Failed. poweredge_model is incorrect or unsupported. Please update the list with the supported models in the correct format"
+# vars file for control_plane_repo
 
 # Usage: install_dsu.yml
 dsu_folder_dest: /root/dsu
 dsu_folder_dest_mode: 0644
 bootstrap_repo_url: https://linux.dell.com/repo/hardware/dsu/bootstrap.cgi
 dsu_rpm_url: https://linux.dell.com/repo/hardware/omnia/os_independent/x86_64/dell-omnia-system-update-1.9.2.1-21.08.00.x86_64.rpm
-dsu_rpm_file: dell-omnia-system-update-1.9.2.1-21.08.00.x86_64.rpm
+dsu_rpm_file: dell-omnia-system-update-1.9.2.1-21.08.00.x86_64.rpm

+ 21 - 0
control_plane/roles/control_plane_security/tasks/enable_dnf_module.yml

@@ -0,0 +1,21 @@
+#  Copyright 2022 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 module idm in Rocky or Centos >= 8.0
+  command: dnf module enable idm:DL1 -y
+  when:
+    - ( ansible_distribution | lower == os_centos ) or
+      ( ansible_distribution | lower == os_rocky )
+    - ( ansible_distribution_version >= os_version )

+ 60 - 0
control_plane/roles/control_plane_security/tasks/firewall_settings.yml

@@ -0,0 +1,60 @@
+#  Copyright 2022 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 firewalld
+  package:
+    name: firewalld
+    state: present
+  tags: firewalld
+
+- name: Start and enable firewalld
+  service:
+    name: firewalld
+    state: started
+    enabled: yes
+  tags: firewalld
+
+- name: Firewall ports addition - tcp/udp ports
+  firewalld:
+    zone: public
+    port: "{{ item }}"
+    permanent: true
+    state: enabled
+  with_items:
+    - "{{ https_port1 }}"
+    - "{{ https_port2 }}"
+    - "{{ ldap_port1 }}"
+    - "{{ ldap_port2 }}"
+    - "{{ kerberos_port1 }}"
+    - "{{ kerberos_port2 }}"
+    - "{{ kerberos_port3 }}"
+    - "{{ kerberos_port4 }}"
+    - "{{ dns_port1 }}"
+    - "{{ dns_port2 }}"
+    - "{{ ntp_port1 }}"
+    - "{{ dt_port1 }}"
+  tags: firewalld
+
+- name: Reload firewalld
+  command: firewall-cmd --reload
+  changed_when: true
+  tags: firewalld
+
+- name: Stop and disable firewalld
+  service:
+    name: firewalld
+    state: stopped
+    enabled: no
+  tags: firewalld

+ 61 - 0
control_plane/roles/control_plane_security/tasks/install_ipa_server.yml

@@ -0,0 +1,61 @@
+#  Copyright 2022 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: Fetch hostname
+  command: hostname
+  register: new_serv_hostname
+  changed_when: false
+
+- name: Set fact for server hostname
+  set_fact:
+    server_hostname_ms: "{{ new_serv_hostname.stdout }}"
+
+- name: Save the hostname
+  copy:
+    dest: "{{ server_file }}"
+    content: |
+      ipaddress: "{{ hostvars['localhost']['ansible_default_ipv4']['address'] }}"
+      server_hostname: "{{ server_hostname_ms }}"
+      server_domain: "{{ domain_name }}"
+    owner: root
+    mode: "{{ file_mode }}"
+
+- name: Uninstall server if it is already installed
+  command: ipa-server-install --uninstall -U
+  changed_when: false
+  failed_when: false
+
+- name: Install ipa server in CentOS > 8 or Rocky 8.4
+  command: >-
+    ipa-server-install -n '{{ domain_name }}' --hostname='{{ server_hostname_ms }}' -a '{{ ipa_admin_password }}'
+    -p '{{ directory_manager_password }}' -r '{{ realm_name }}' --setup-dns --no-forwarders --no-reverse --no-ntp -U
+  changed_when: true
+  no_log: true
+  when:
+    - ( ansible_distribution | lower == os_centos ) or
+      ( ansible_distribution | lower == os_rocky )
+    - ( ansible_distribution_version >= os_version )
+
+- name: Authenticate as admin
+  shell: set -o pipefail && echo $'{{ ipa_admin_password }}' | kinit admin
+  no_log: true
+  changed_when: false
+
+- name: Replace the /etc/resolv.conf file
+  copy:
+    src: "{{ temp_resolv_conf_path }}"
+    dest: "{{ resolv_conf_path }}"
+    mode: "{{ file_mode }}"
+    remote_src: yes

+ 41 - 0
control_plane/roles/control_plane_security/tasks/install_packages.yml

@@ -0,0 +1,41 @@
+#  Copyright 2022 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 packages
+  package:
+    name: "{{ ipa_server_packages }}"
+    state: present
+  tags: install
+
+- name: Take a backup of /etc/resolv.conf
+  copy:
+    src: "{{ resolv_conf_path }}"
+    dest: "{{ temp_resolv_conf_path }}"
+    mode: "{{ resolv_file_mode }}"
+    remote_src: yes
+
+- name: Add the domain name in /etc/resolv.conf
+  replace:
+    path: "{{ temp_resolv_conf_path }}"
+    regexp: "search"
+    replace: "search {{ domain_name }}"
+  register: replace_output
+
+- name: Add the domain name in /etc/resolv.conf when there is no domain name
+  replace:
+    path: "{{ temp_resolv_conf_path }}"
+    regexp: "# Generated by NetworkManager"
+    replace: "# Generated by NetworkManager\nsearch {{ domain_name }}"
+  when: replace_output.msg | length == 0

+ 39 - 0
control_plane/roles/control_plane_security/tasks/main.yml

@@ -0,0 +1,39 @@
+#  Copyright 2022 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 ports of manager and login node to firewall
+  include_tasks: firewall_settings.yml
+  when:
+    - enable_security_support
+
+- name: Enable module idm in Rocky or Centos >= 8.0
+  include_tasks: enable_dnf_module.yml
+  when:
+    - enable_security_support
+
+- name: Update Packages
+  include_tasks: update_package.yml
+  when:
+    - enable_security_support
+
+- name: Install required packages
+  include_tasks: install_packages.yml
+  when:
+    - enable_security_support
+
+- name: Install free-ipa server
+  include_tasks: install_ipa_server.yml
+  when:
+    - enable_security_support

+ 23 - 0
control_plane/roles/control_plane_security/tasks/update_package.yml

@@ -0,0 +1,23 @@
+#  Copyright 2022 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: Update nss package to install ipa server/client
+  command: yum update nss -y
+  changed_when: false
+  args:
+    warn: false
+  when:
+    - ( ansible_distribution | lower == os_centos )
+    - ( ansible_distribution_version < os_version )

+ 50 - 0
control_plane/roles/control_plane_security/vars/main.yml

@@ -0,0 +1,50 @@
+#  Copyright 2022 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.
+---
+
+# Usage: set_fqdn.yml
+etc_hosts_file_dest: /etc/hosts
+file_mode: '0644'
+
+# Usage: firewall_settings.yml
+https_port1: "80/tcp"
+https_port2: "443/tcp"
+ldap_port1: "389/tcp"
+ldap_port2: "636/tcp"
+kerberos_port1: "88/tcp"
+kerberos_port2: "464/tcp"
+kerberos_port3: "88/udp"
+kerberos_port4: "464/udp"
+dns_port1: "53/tcp"
+dns_port2: "53/udp"
+dt_port1: "7389/tcp"
+ntp_port1: "123/udp"
+
+# Usage: enable_dnf_module.yml
+os_centos: 'centos'
+os_rocky: 'rocky'
+os_version: '8.0'
+
+# Usage: install_packages.yml
+ipa_server_packages:
+  - bind
+  - bind-dyndb-ldap
+  - ipa-server-dns
+  - freeipa-server
+
+# Usage: install_ipa_server.yml
+resolv_conf_path: /etc/resolv.conf
+temp_resolv_conf_path: /tmp/resolv.conf
+resolv_file_mode: '0644'
+server_file: "{{ playbook_dir }}/roles/control_plane_security/files/.ipavars.yml"

+ 64 - 24
control_plane/roles/deploy_job_templates/tasks/group_inventory.yml

@@ -12,35 +12,75 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ---
+- name: Initializing variables
+  set_fact:
+    compute_list: []
+    non_compute_list: []
+    component_roles: []
+
 - name: Get the hosts in node_inventory
-  command: >-
-    awx --conf.host {{ awx_host }} --conf.username {{ awx_admin_user }} --conf.password {{ awx_password }}
-    --conf.insecure hosts list --inventory {{ node_inventory }} -f human --filter "name"
+  command: awx --conf.host {{ awx_host }} --conf.username {{ awx_admin_user }} --conf.password {{ awx_password }} --conf.insecure hosts list --inventory {{ node_inventory }} -f human --filter "name"
   changed_when: false
   no_log: true
   register: hosts_list
 
-- name: Add the host to compute group in node_inventory if it exists
-  awx.awx.tower_group:
-    name: "{{ item.split(',')[3] }}"
-    inventory: "{{ node_inventory }}"
-    preserve_existing_hosts: true
-    hosts:
-      - "{{ item.split(',')[2] }}"
-    tower_config_file: "{{ tower_config_file }}"
+- name: Converting csv values to list
+  read_csv:
+    path: "{{ host_mapping_file_path }}"
+    delimiter: ','
+  register: mapping
+
+- name: Collecting compute node ip's from host mapping file
+  set_fact:
+      compute_list: "{{ compute_list + [ item.IP ] }}"
   when:
-    - item.split(',')[2] != "IP"
-    - item.split(',')[2] in hosts_list.stdout 
-    - item.split(',')[3] == "compute"
+    - item.Component_role ==  compute_node
+    - item.IP in hosts_list.stdout
+  no_log: true
+  with_items:
+      - "{{ mapping.list }}"
 
-- name: Add the host to other groups in node_inventory if it exists
-  awx.awx.tower_group:
-    name: "{{ item.split(',')[3] }}"
-    inventory: "{{ node_inventory }}"
-    hosts:
-      - "{{ item.split(',')[2] }}"
-    tower_config_file: "{{ tower_config_file }}"
+- name: Collecting manager,nfs_node,login_nodes ip's from host mapping file
+  set_fact:
+      non_compute_list: "{{ non_compute_list + [ item.IP ] }}"
+      component_roles: "{{ component_roles + [item.Component_role] }}"
   when:
-    - item.split(',')[2] != "IP"
-    - item.split(',')[2] in hosts_list.stdout
-    - item.split(',')[3] != "compute"
+    - item.Component_role != compute_node
+  no_log: true
+  with_items:
+      - "{{ mapping.list }}"
+
+- name: Adding ips to compute node in awx ui
+  block:
+    - name: Add the host to compute group in node_inventory if it exists
+      awx.awx.tower_group:
+        name: "{{ compute_node }}"
+        inventory: "{{ node_inventory }}"
+        hosts: "{{ compute_list }}"
+        tower_config_file: "{{ tower_config_file }}"
+      register: compute_output
+      no_log: true
+  rescue:
+    - name: Failed to add ip's to compute node in awx ui
+      fail:
+        msg: "{{ compute_output.stdout }}"
+
+- name: Adding ips to manager,nfs_node,login_node in awx ui
+  block:
+    - name: Add the host to other groups in node_inventory if it exists
+      awx.awx.tower_group:
+        name: "{{ item.0 }}"
+        inventory: "{{ node_inventory }}"
+        hosts:
+          - "{{ item.1 }}"
+        tower_config_file: "{{ tower_config_file }}"
+      when: item.1 in hosts_list.stdout
+      with_together:
+          - "{{ component_roles }}"
+          - "{{ non_compute_list }}"
+      register: non_compute_output
+      no_log: true
+  rescue:
+    - name: Failed to add ip's to manager,nfs_node,login_node
+      fail:
+        msg: "{{ non_compute_output.stdout }}"

+ 0 - 1
control_plane/roles/deploy_job_templates/tasks/main.yml

@@ -186,7 +186,6 @@
 
 - name: Group the hosts in node_inventory when mapping file is present
   include_tasks: "{{ role_path }}/tasks/group_inventory.yml"
-  with_items: "{{ mapping_file.stdout_lines }}"
   when: host_mapping_file and component_role_support
 
 - name: Launch deploy_omnia job template

+ 1 - 0
control_plane/roles/deploy_job_templates/vars/main.yml

@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ---
+compute_node: "compute"
 base_vars_file: "{{ role_path }}/../../input_params/base_vars.yml"
 awx_namespace: awx
 awx_admin_user: admin

+ 71 - 0
control_plane/roles/provision_cobbler/files/Dockerfile_leap

@@ -0,0 +1,71 @@
+FROM registry.opensuse.org/opensuse/leap:15.3
+
+#Enable all repose
+RUN zypper mr -ea
+
+# Refresh and update the repo
+RUN zypper --gpg-auto-import-keys refresh
+RUN zypper --gpg-auto-import-keys up -y
+
+#Enable systemd
+RUN zypper in -y dbus-1 systemd-sysvinit
+RUN cp /usr/lib/systemd/system/dbus.service /etc/systemd/system/; \
+    sed -i 's/OOMScoreAdjust=-900//' /etc/systemd/system/dbus.service
+
+VOLUME ["/sys/fs/cgroup", "/run"]
+
+RUN zypper in -y git-core
+RUN git clone -b v3.2.2 https://github.com/cobbler/cobbler.git
+RUN cd cobbler/
+
+RUN mkdir /root/omnia
+
+RUN zypper in --no-confirm python3-librepo \
+                      python3-schema \
+                      syslinux \
+                      wget \
+                      dhcp-server \
+                      python3-pykickstart \
+                      dnf-plugins-core \
+                      cronie \
+                      xinetd \
+                      python3-coverage \
+                      python3-Cheetah3 \
+                      python3-netaddr \
+                      python3-devel \
+                      python3-future \
+                      apache2-mod_wsgi-python3 \
+                      gcc \
+                      python-rpm-macros \
+                      rpm-build \
+                      ansible \
+                      grub2-x86_64-efi \
+                      shim \
+                      yum-utils \
+                      python3-Sphinx \
+                      python3-wheel \
+                      bash-completion \
+                      tftp \
+                      vim
+
+RUN useradd -ms /bin/bash dhcpd
+
+#Copy Configuration files
+COPY settings.yaml /etc/cobbler/settings.yaml
+COPY dhcp.template  /etc/cobbler/dhcp.template
+COPY modules.conf  /etc/cobbler/modules.conf
+COPY tftp /etc/xinetd.d/tftp
+COPY .users.digest /etc/cobbler/users.digest
+COPY cobbler_configurations_leap.yml /root
+COPY tftp.yml /root
+COPY inventory_creation.yml /root
+COPY multi_cluster_provisioning.yml /root
+
+EXPOSE 69 80 443 25151
+
+VOLUME [ "/srv/www/cobbler", "/var/lib/cobbler/backup", "/mnt" ]
+
+RUN systemctl enable apache2
+RUN systemctl enable dhcpd
+
+CMD ["sbin/init"]

+ 8 - 8
control_plane/roles/provision_cobbler/files/Dockerfile

@@ -1,4 +1,4 @@
-FROM centos:8.3.2011
+FROM rockylinux/rockylinux:8.5
 
 # RPM REPOs
 RUN dnf install -y \
@@ -10,10 +10,6 @@ RUN dnf update -y \
     && dnf clean all \
     && rm -rf /var/cache/dnf
 
-RUN dnf install -y git
-RUN git clone -b v3.2.2 https://github.com/cobbler/cobbler.git
-RUN cd cobbler/
-
 RUN mkdir /root/omnia
 
 RUN dnf install -y mod_ssl \
@@ -44,11 +40,14 @@ RUN dnf install -y mod_ssl \
         && dnf clean all \
         &&  rm -rf /var/cache/dnf
 
-RUN yum install -y  grub2-efi-x64 shim-x64 
+RUN yum install -y  grub2-efi-x64 shim-x64
 RUN yum install -y yum-utils
 RUN dnf config-manager --set-enabled powertools
 RUN dnf install -y python3-sphinx
 RUN pip3 install wheel
+RUN dnf module enable -y cobbler
+RUN dnf install -y cobbler
+RUN dnf install -y cobbler-web
 
 #Copy Configuration files
 COPY settings.yaml /etc/cobbler/settings.yaml
@@ -56,9 +55,10 @@ COPY dhcp.template  /etc/cobbler/dhcp.template
 COPY modules.conf  /etc/cobbler/modules.conf
 COPY tftp /etc/xinetd.d/tftp
 COPY .users.digest /etc/cobbler/users.digest
-COPY cobbler_configurations.yml /root
+COPY cobbler_configurations_rocky.yml /root
 COPY tftp.yml /root
 COPY inventory_creation.yml /root
+COPY multi_cluster_provisioning.yml /root
 
 EXPOSE 69 80 443 25151
 
@@ -67,4 +67,4 @@ VOLUME [ "/var/www/cobbler", "/var/lib/cobbler/backup", "/mnt" ]
 RUN systemctl enable httpd
 RUN systemctl enable dhcpd
 
-CMD ["sbin/init"]
+CMD ["sbin/init"]

+ 140 - 0
control_plane/roles/provision_cobbler/files/cobbler_configurations_leap.yml

@@ -0,0 +1,140 @@
+#  Copyright 2022 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: Initial cobbler setup
+  hosts: localhost
+  connection: local
+  gather_facts: false
+  tasks:
+  - name: Inside cobbler container
+    debug:
+      msg: "Hiii! I am cobbler"
+
+  - name: Make
+    command: make rpms
+    args:
+      chdir: /cobbler
+    changed_when: false
+
+  - name: Install cobbler and cobbler-web
+    command: zypper in -y --allow-unsigned-rpm cobbler-3.2.2-1.noarch.rpm cobbler-web-3.2.2-1.noarch.rpm
+    args:
+      chdir: /cobbler/rpm-build
+    changed_when: false
+    
+  - name: Run script
+    shell: sh ./mkgrub.sh
+    args:
+      chdir: /usr/share/cobbler/bin
+    changed_when: false
+  
+  - name: Add settings to http
+    shell: echo "LoadModule wsgi_module modules/mod_wsgi_python3.so" >/etc/apache2/conf.d/wsgi.conf
+    changed_when: false
+
+  - name: Add interface to the /etc/sysconfig/dhcpd
+    replace:
+      path: "/etc/sysconfig/dhcpd"
+      regexp: "^DHCPD_INTERFACE=\"\""
+      replace: "DHCPD_INTERFACE={{ host_network_nic }}"
+
+  - name: Enable cobbler
+    command: systemctl enable {{ item }}
+    with_items:
+      - cobblerd
+      - tftp
+    changed_when: false
+
+  - name: Restart httpd
+    service:
+      name: "{{ item }}"
+      state: restarted
+    loop:
+      - apache2
+      - cobblerd
+
+  - name: Start services
+    service:
+      name: "{{ item }}"
+      state: started
+    loop:
+      - cobblerd
+      - tftp
+
+  - name: Adding curl
+    shell: export PATH="/usr/bin/curl:$PATH"
+
+  - name: Run import command
+    command: cobbler import --arch=x86_64 --path=/mnt/{{ provision_os }} --name="{{ provision_os }}"
+    changed_when: false
+
+  - name: Kickstart profile - leap
+    copy:
+      src: "/root/leap15.xml"
+      dest: "/var/lib/cobbler/templates/sample_autoyast.xml"
+      mode: "{{ file_perm }}"
+    tags: install
+
+  - name: Pxe menu
+    copy:
+      src: "/root/omnia/control_plane/roles/provision_cobbler/files/menu.yml"
+      dest: "/etc/cobbler/boot_loader_conf/pxedefault.template"
+      mode: "{{ file_perm }}"
+    tags: install
+
+  - name: Assign default grub option
+    replace:
+      path: "/var/lib/cobbler/grub_config/grub/grub.cfg"
+      regexp: "^set default='local'"
+      replace: "set default='1'"
+    tags: install
+
+  - name: Assign default grub timeout
+    replace:
+      path: "/var/lib/cobbler/grub_config/grub/grub.cfg"
+      regexp: '^set timeout=80'
+      replace: 'set timeout=10'
+    tags: install
+
+  - name: Syncing of cobbler
+    command: cobbler sync
+    changed_when: false 
+
+  - name: Restart cobblerd, http, xinetd and dhcpd
+    service:
+      name: "{{ item }}"
+      state: restarted
+    loop:
+      - cobblerd
+      - apache2
+      - xinetd
+      - dhcpd
+
+  - name: Fetch ansible-playbook path
+    command: whereis ansible-playbook
+    changed_when: false
+    register: ansible_playbook_path
+
+  - name: Add tftp cron job
+    cron:
+      name: Start tftp service
+      minute: "*"
+      job: "{{ ansible_playbook_path.stdout.split(' ')[1] }} /root/tftp.yml"
+
+  - name: Add inventory cron job
+    cron:
+      name: Create inventory
+      minute: "*/5"
+      job: "{{ ansible_playbook_path.stdout.split(' ')[1] }} /root/inventory_creation.yml"

+ 11 - 35
control_plane/roles/provision_cobbler/files/cobbler_configurations.yml

@@ -1,4 +1,4 @@
-#  Copyright 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
+#  Copyright 2022 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.
@@ -22,18 +22,6 @@
     debug:
       msg: "Hiii! I am cobbler"
 
-  - name: Make
-    command: make rpms
-    args:
-      chdir: /cobbler
-    changed_when: false
-
-  - name: Install cobbler and cobbler-web
-    command: dnf install -y cobbler-3.2.2-1.el8.noarch.rpm cobbler-web-3.2.2-1.el8.noarch.rpm
-    args:
-      chdir: /cobbler/rpm-build
-    changed_when: false
-  
   - name: Run script
     shell: sh ./mkgrub.sh
     args:
@@ -49,18 +37,6 @@
         LoadModule wsgi_module modules/mod_wsgi_python3.so
         LoadModule proxy_module modules/mod_proxy.so
 
-  - name: Cobbler web
-    blockinfile:
-      state: present
-      insertafter: '^<VirtualHost '
-      path: /etc/httpd/conf.d/cobbler_web.conf
-      block: |
-         ServerName localhost
-         SSLEngine on
-         SSLCipherSuite PROFILE=SYSTEM
-         SSLCertificateFile /etc/pki/tls/certs/localhost.crt
-         SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
-
   - name: Add settings to http
     shell: echo "LoadModule wsgi_module modules/mod_wsgi_python3.so" >/etc/httpd/conf.d/wsgi.conf
     changed_when: false
@@ -92,37 +68,37 @@
     shell: export PATH="/usr/bin/curl:$PATH"
 
   - name: Run import command
-    command: cobbler import --arch=x86_64 --path=/mnt --name="{{ name_iso }}"
+    command: cobbler import --arch=x86_64 --path=/mnt/{{ provision_os }} --name="{{ provision_os }}"
     changed_when: false
 
   - name: Kickstart profile - centos
     copy:
       src: "/root/centos7.ks"
       dest: "/var/lib/cobbler/templates/sample.ks"
-      mode: 0775
+      mode: "{{ file_perm }}"
     tags: install
-    when: name_iso == "centos"
+    when: provision_os == "centos"
 
   - name: Kickstart profile - rocky
     copy:
       src: "/root/rocky8.ks"
       dest: "/var/lib/cobbler/templates/sample.ks"
-      mode: 0775
+      mode: "{{ file_perm }}"
     tags: install
-    when: name_iso == "rocky"
+    when: provision_os == "rocky"
 
   - name: Pxe menu
     copy:
       src: "/root/omnia/control_plane/roles/provision_cobbler/files/menu.yml"
       dest: "/etc/cobbler/boot_loader_conf/pxedefault.template"
-      mode: 0775
+      mode: "{{ file_perm }}"
     tags: install
 
   - name: Assign default grub option
     replace:
       path: "/var/lib/cobbler/grub_config/grub/grub.cfg"
-      regexp: "^set default=\'local\'"
-      replace: "set default=\'1\'"
+      regexp: "^set default='local'"
+      replace: "set default='1'"
     tags: install
 
   - name: Assign default grub timeout
@@ -134,7 +110,7 @@
 
   - name: Syncing of cobbler
     command: cobbler sync
-    changed_when: false 
+    changed_when: false
 
   - name: Restart cobblerd, http, xinetd and dhcpd
     service:
@@ -161,4 +137,4 @@
     cron:
       name: Create inventory
       minute: "*/5"
-      job: "{{ ansible_playbook_path.stdout.split(' ')[1] }} /root/inventory_creation.yml"
+      job: "{{ ansible_playbook_path.stdout.split(' ')[1] }} /root/inventory_creation.yml"

+ 8 - 2
control_plane/roles/provision_cobbler/files/inventory_creation.yml

@@ -1,11 +1,17 @@
 - hosts: localhost
   connection: local
-  gather_facts: false
+  gather_facts: true
   tasks:
-    - name: Read dhcp file
+    - name: Read dhcp file for rocky
       set_fact:
         var: "{{ lookup('file', '/var/lib/dhcpd/dhcpd.leases').split()| unique | select| list }}"
+      when: ansible_facts['distribution'] | lower == "rocky"
 
+    - name: Read dhcp file for leap
+      set_fact:
+        var: "{{ lookup('file', '/var/lib/dhcp/db/dhcpd.leases').split()| unique | select| list }}"
+      when: ("leap" in ansible_facts['distribution'] | lower)
+    
     - name: Filter the ip
       set_fact:
         vars_new: "{{ var| ipv4('address')| to_nice_yaml}}"

+ 1 - 1
control_plane/roles/provision_cobbler/files/k8s_cobbler.yml

@@ -25,7 +25,7 @@ spec:
             type: Directory
         - name: mnt-iso
           hostPath:
-            path: /mnt/iso/
+            path: /mnt/
             type: Directory
       containers:
         - name: cobbler

+ 85 - 0
control_plane/roles/provision_cobbler/files/multi_cluster_provisioning.yml

@@ -0,0 +1,85 @@
+#  Copyright 2022 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: Initial cobbler setup
+  hosts: localhost
+  connection: local
+  gather_facts: false
+  tasks:
+    - name: Initialize variables
+      set_fact:
+        multi_profile: false
+        grub_option: 1
+
+    - name: Run import command
+      command: cobbler import --arch=x86_64 --path=/mnt/{{ provision_os }} --name="{{ provision_os }}"
+      changed_when: false
+
+    - name: Kickstart profile - centos
+      copy:
+        src: "/root/centos7.ks"
+        dest: "/var/lib/cobbler/templates/sample.ks"
+        mode: "{{ file_perm }}"
+      tags: install
+      when: provision_os == "centos"
+
+    - name: Kickstart profile - rocky
+      copy:
+        src: "/root/rocky8.ks"
+        dest: "/var/lib/cobbler/templates/sample.ks"
+        mode: "{{ file_perm }}"
+      tags: install
+      when: provision_os == "rocky"
+
+    - name: Kickstart profile - leap
+      copy:
+        src: "/root/leap15.xml"
+        dest: "/var/lib/cobbler/templates/sample_autoyast.xml"
+        mode: "{{ file_perm }}"
+      tags: install
+      when: provision_os == "leap"
+
+    - name: Get the cobbler profile list
+      command: cobbler profile list
+      changed_when: false
+      register: cobbler_profile_list
+      failed_when: false
+
+    - name: Check if cobbler_profile_list has more that one profile
+      set_fact:
+        multi_profile: true
+      when:
+        - cobbler_profile_list.stdout_lines| length > 1
+
+    - name: Check if the provision os is in cobbler_profile_list
+      set_fact:
+        grub_option: "{{ index + 1 }}"
+      when:
+        - provision_os in item
+        - multi_profile
+      loop: "{{ cobbler_profile_list.stdout_lines | flatten(levels=1) }}"
+      loop_control:
+        index_var: index
+
+    - name: Assign default grub option
+      replace:
+        path: "/var/lib/cobbler/grub_config/grub/grub.cfg"
+        regexp: "^set default=.*"
+        replace: "set default='{{ grub_option }}'"
+      tags: install
+
+    - name: Syncing of cobbler
+      command: cobbler sync
+      changed_when: false

+ 86 - 0
control_plane/roles/provision_cobbler/files/temp_leap15.xml

@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!DOCTYPE profile>
+<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns">
+  <install>
+    <init>
+      <info_file>
+        <![CDATA[
+          install: http://ip/cblr/links/leap-x86_64/
+          textmode: 1]]>
+      </info_file>
+    </init>
+  </install>
+  <general>
+    <mode>
+      <confirm config:type="boolean">false</confirm>
+      <final_reboot config:type="boolean">true</final_reboot>
+    </mode>
+  </general>
+  <bootloader t="map">
+    <loader_type>default</loader_type>
+  </bootloader>
+  <host t="map">
+    <hosts t="list">
+      <hosts_entry t="map">
+        <host_address>127.0.0.1</host_address>
+        <names t="list">
+          <name>localhost</name>
+        </names>
+      </hosts_entry>
+    </hosts>
+  </host>
+  <networking t="map">
+    <dns t="map">
+      <dhcp_hostname t="boolean">false</dhcp_hostname>
+      <hostname>localhost.localdomain</hostname>
+      <resolv_conf_policy>auto</resolv_conf_policy>
+    </dns>
+  </networking>
+  <services-manager t="map">
+    <default_target>multi-user</default_target>
+    <services t="map">
+      <enable t="list">
+        <service>chronyd</service>
+        <service>sshd</service>
+      </enable>
+    </services>
+  </services-manager>
+  <software t="map">
+    <install_recommended t="boolean">true</install_recommended>
+    <instsource/>
+    <packages t="list">
+      <package>openssh</package>
+      <package>firewalld</package>
+      <package>chrony</package>
+    </packages>
+  </software>
+  <ssh_import t="map">
+    <copy_config t="boolean">false</copy_config>
+    <import t="boolean">false</import>
+  </ssh_import>
+  <timezone t="map">
+    <timezone>yast_timezone</timezone>
+  </timezone>
+  <users t="list">
+    <user t="map">
+      <authorized_keys t="list"/>
+      <encrypted t="boolean">true</encrypted>
+      <fullname>root</fullname>
+      <gid>0</gid>
+      <home>/root</home>
+      <home_btrfs_subvolume t="boolean">false</home_btrfs_subvolume>
+      <password_settings t="map">
+        <expire/>
+        <flag/>
+        <inact/>
+        <max/>
+        <min/>
+        <warn/>
+      </password_settings>
+      <shell>/bin/bash</shell>
+      <uid>0</uid>
+      <user_password>yast_password</user_password>
+      <username>root</username>
+    </user>
+  </users>
+</profile>

+ 0 - 0
control_plane/roles/provision_cobbler/files/tftp.yml


Some files were not shown because too many files changed in this diff