Add support for CentOS 8.x image on Azure (#377)

* Add support for CentOS 8.x image on Azure

	* Add a new key `azure_image_reference` to `muchos.props.example` file
	* Import GPG key to install Grafana, Elasticsearch on CentOS 8
	* Disable GPG check for InfluxDB as the package is not digitally signed
	* Update `README` & create `azure-image-reference.md` under `docs` section

Co-authored-by: Karthick Narendran <kanarend@microsoft.com>
diff --git a/README.md b/README.md
index b08b202..8632dfa 100644
--- a/README.md
+++ b/README.md
@@ -168,6 +168,12 @@
 * `vnet` to provide the name of the VNET that your cluster nodes should use. A new VNET with this name will be
   created if it doesn't already exist
 * `subnet` to provide a name for the subnet within which the cluster resources will be deployed
+* `azure_image_reference` allows you to specify the CentOS image SKU in the format as shown below. To configure 
+  CentOS 8.x, please follow [these steps](docs/azure-image-reference.md).
+  ```bash
+  offer|publisher|sku|version|
+  Ex: CentOS|OpenLogic|7.5|latest|
+  ```  
 * `numnodes` to change the cluster size in terms of number of nodes deployed
 * `data_disk_count` to specify how many persistent data disks are attached to each node and will be used by HDFS.
    If you would prefer to use ephemeral / storage for Azure clusters, please follow [these steps](docs/azure-ephemeral-disks.md).
diff --git a/ansible/roles/azure/tasks/create_vmss.yml b/ansible/roles/azure/tasks/create_vmss.yml
index 3094237..9b1438b 100644
--- a/ansible/roles/azure/tasks/create_vmss.yml
+++ b/ansible/roles/azure/tasks/create_vmss.yml
@@ -142,11 +142,16 @@
     enable_accelerated_networking: yes
     single_placement_group: "{{ single_placement_group | default(omit) }}"
     image:
-      offer: CentOS
-      publisher: OpenLogic
-      sku: 7.5
-      version: latest
+      offer: "{{ image_offer if image_offer else omit }}"
+      publisher: "{{ image_publisher if image_publisher else omit }}"
+      sku: "{{ image_sku if image_sku else omit }}"
+      version: "{{ image_version if image_version else omit }}"
     data_disks: "{{ luns_dict if data_disk_count > 0 else omit }}"
+  vars:
+  - image_offer: "{{ azure_image_reference.split('|')[0] }}"
+  - image_publisher: "{{ azure_image_reference.split('|')[1] }}"
+  - image_sku: "{{ azure_image_reference.split('|')[2] }}"
+  - image_version: "{{ azure_image_reference.split('|')[3] }}"
   tags: create_vmss
 
 # SECTION 4: Automatically populate entries in the hosts file and in the muchos.props file, based on the VMSS node details
diff --git a/ansible/roles/common/tasks/azure_oms_selinux.yml b/ansible/roles/common/tasks/azure_oms_selinux.yml
index 85ae915..56d7ab3 100644
--- a/ansible/roles/common/tasks/azure_oms_selinux.yml
+++ b/ansible/roles/common/tasks/azure_oms_selinux.yml
@@ -21,6 +21,11 @@
 - name: Copy Policy file OMS-collectd.te
   copy: src=roles/common/files/OMS-collectd.te dest=/home/{{ cluster_user }}/SEPolicyFiles  owner={{ cluster_user }} group={{ cluster_group }}
 
+# Update the policy file to use 'statsd_port_t' added in CentOS 8.2 to avoid runtime failures
+- name: Update Policy file OMS-collectd.te for CentOS 8.2 and later
+  replace: regexp=unreserved_port_t replace=statsd_port_t path=/home/{{ cluster_user }}/SEPolicyFiles/OMS-collectd.te owner={{ cluster_user }} group={{ cluster_group }}
+  when: ansible_facts['distribution_version'] is version('8.2', '>=')
+
 - name: Copy Policy file OMS-logrotate.te
   copy: src=roles/common/files/OMS-logrotate.te dest=/home/{{ cluster_user }}/SEPolicyFiles  owner={{ cluster_user }} group={{ cluster_group }}
 
diff --git a/ansible/roles/common/tasks/main.yml b/ansible/roles/common/tasks/main.yml
index 385666a..c0eb250 100644
--- a/ansible/roles/common/tasks/main.yml
+++ b/ansible/roles/common/tasks/main.yml
@@ -33,12 +33,34 @@
       - patch
       - "{{ java_package }}"
       - collectd-zookeeper
-      - policycoreutils-python
     state: present
   register: yumresult
   retries: 10
   delay: 15
   until: yumresult is not failed
+- name: "Install package specific to CentOS 7"
+  yum:
+    name:
+      - policycoreutils-python
+    state: present
+  register: yumresult_centos7
+  retries: 10
+  delay: 15
+  until: yumresult_centos7 is not failed
+  when: ansible_facts['distribution_major_version'] == "7"
+- name: "Install packages specific to CentOS 8"
+  yum:
+    name:
+      - python3-policycoreutils
+      - collectd-disk
+      - collectd-write_http
+      - make
+    state: present
+  register: yumresult_centos8
+  retries: 10
+  delay: 15
+  until: yumresult_centos8 is not failed
+  when: ansible_facts['distribution_major_version'] == "8"
 - name: "get exact jdk folder path"
   find:
     file_type: directory
diff --git a/ansible/roles/elasticsearch/tasks/main.yml b/ansible/roles/elasticsearch/tasks/main.yml
index d041127..794c8a0 100644
--- a/ansible/roles/elasticsearch/tasks/main.yml
+++ b/ansible/roles/elasticsearch/tasks/main.yml
@@ -29,6 +29,13 @@
     checksum: "{{ elasticsearch_checksum }}"
     force: no
 
+- name: "Import GPG key for CentOS 8.0 and later"
+  become: true
+  rpm_key:
+    key: https://artifacts.elastic.co/GPG-KEY-elasticsearch
+    state: present
+  when: ansible_facts['distribution_version'] is version('8.0', '>=')
+
 # Install elasticsearch
 - name: "ensure elasticsearch is installed"
   become: true
diff --git a/ansible/roles/grafana/tasks/main.yml b/ansible/roles/grafana/tasks/main.yml
index 55a02cc..9e7365f 100644
--- a/ansible/roles/grafana/tasks/main.yml
+++ b/ansible/roles/grafana/tasks/main.yml
@@ -22,6 +22,12 @@
     dest: /tmp/{{ grafana_rpm }}
     checksum: "{{ grafana_checksum }}"
     force: no
+- name: "Import GPG key for CentOS 8.0 and later"
+  become: true
+  rpm_key:
+    key: https://grafanarel.s3.amazonaws.com/RPM-GPG-KEY-grafana-old
+    state: present
+  when: ansible_facts['distribution_version'] is version('8.0', '>=')
 - name: "ensure grafana is installed"
   yum: name=/tmp/{{ grafana_rpm }} state=present
 - name: "configure grafana"
diff --git a/ansible/roles/influxdb/tasks/main.yml b/ansible/roles/influxdb/tasks/main.yml
index 1ab35f5..807df42 100644
--- a/ansible/roles/influxdb/tasks/main.yml
+++ b/ansible/roles/influxdb/tasks/main.yml
@@ -23,7 +23,7 @@
     checksum: "{{ influxdb_checksum }}"
     force: no
 - name: "ensure influxdb is installed"
-  yum: name=/tmp/{{ influxdb_rpm }} state=present
+  yum: name=/tmp/{{ influxdb_rpm }} state=present disable_gpg_check=yes
 - name: "configure influxdb"
   template: src=influxdb-9.4.2.conf dest=/etc/opt/influxdb/influxdb.conf
   notify:
diff --git a/ansible/scripts/install_ansible.sh b/ansible/scripts/install_ansible.sh
index bfb7c67..5a4eb35 100755
--- a/ansible/scripts/install_ansible.sh
+++ b/ansible/scripts/install_ansible.sh
@@ -47,7 +47,12 @@
 fi
 
 # install lxml as it is a dependency for the maven_artifact Ansible module
-sudo yum install -q -y python-lxml
+centos_version=`cat /etc/os-release | grep '^VERSION_ID' | cut -d'"' -f2`
+if [ $centos_version -eq 7 ]; then
+   sudo yum install -q -y python-lxml
+elif [ $centos_version -eq 8 ]; then
+   sudo yum install -q -y python3-lxml
+fi
 
 # install jq to ease JSON parsing on the proxy
 sudo yum install -y jq
diff --git a/conf/muchos.props.example b/conf/muchos.props.example
index fa1ee7c..eda345c 100644
--- a/conf/muchos.props.example
+++ b/conf/muchos.props.example
@@ -114,6 +114,9 @@
 subnet = subnet1
 # The CIDR prefix used for the single subnet within the virtual network.
 subnet_cidr = 10.1.0.0/16
+# Azure image reference defined as a pipe-delimited string in the format offer|publisher|sku|version|
+# Please refer 'Launching an Azure cluster' section of the README before making changes 
+azure_image_reference = CentOS|OpenLogic|7.5|latest|
 # Size of the cluster to provision.
 # A virtual machine scale set (VMSS) with these many VMs will be created.
 # The minimum allowed size for this is 3 nodes for non-HA & 4 nodes for HA setup
diff --git a/docs/azure-image-reference.md b/docs/azure-image-reference.md
new file mode 100644
index 0000000..75b6d6e
--- /dev/null
+++ b/docs/azure-image-reference.md
@@ -0,0 +1,25 @@
+Configure Azure image with CentOS 8.x
+--------------------------------------
+
+To configure CentOS 8.x, simply modify the `sku` as shown below. This will install CentOS 8.2 Generation 2 Azure VMs. To know more about Generation 2 VMs on Azure, please visit the [doc](https://docs.microsoft.com/en-us/azure/virtual-machines/generation-2)
+```bash
+CentOS|OpenLogic|8_2-gen2|latest|
+```
+Run the Azure CLI command to determine the list of SKU's available for CentOS in a given region
+```bash
+az vm image list-skus -l <region> -f CentOS -p OpenLogic -o table
+```
+For illustration, provided a sample output that displays the sku list from `westus2` region. The sku name `8_1, 8_2` implicitly refers to Generation 1 Azure VMs.
+```bash
+$ az vm image list-skus -l westus2 -f CentOS -p OpenLogic -o table
+Location    Name
+--------   ------
+westus2     7_8-gen2
+westus2     8.0
+westus2     8_0-gen2
+westus2     8_1
+westus2     8_1-gen2
+westus2     8_2
+westus2     8_2-gen2
+```
+
diff --git a/lib/muchos/config/azure.py b/lib/muchos/config/azure.py
index 3becbd4..ddc3f89 100644
--- a/lib/muchos/config/azure.py
+++ b/lib/muchos/config/azure.py
@@ -143,6 +143,11 @@
     def azure_fileshare_password(self):
         return self.get("azure", "azure_fileshare_password")
 
+    @ansible_host_var
+    @default("CentOS|OpenLogic|7.5|latest|")
+    def azure_image_reference(self):
+        return self.get("azure", "azure_image_reference")
+
     @ansible_host_var(name="az_oms_integration_needed")
     @default(False)
     @is_valid(is_in([True, False]))