Add ability to enable huge pages

Related-Prod: https://mirantis.jira.com/browse/PRODX-8500
Change-Id: I258489da117ba1cc4820c92dbcf77ccd5d33bee9
diff --git a/de/heat-templates/env/mstr1-wrkr5-cmp3-acmp2-gtw0.yaml b/de/heat-templates/env/mstr1-wrkr5-cmp3-acmp2-gtw0.yaml
index 5e71272..0b51415 100644
--- a/de/heat-templates/env/mstr1-wrkr5-cmp3-acmp2-gtw0.yaml
+++ b/de/heat-templates/env/mstr1-wrkr5-cmp3-acmp2-gtw0.yaml
@@ -33,6 +33,8 @@
   acmps_flavor: 'system.compact.openstack.control.ephemeral.numa'
   storage_frontend_network_cidr: '10.12.1.0/24'
   storage_backend_network_cidr: '10.12.0.0/24'
+  # Enable only 1 size of huge pages because of https://mirantis.jira.com/browse/PRODX-8809
+  huge_pages: '0,5000'
   hardware_metadata: |
     '00:00:00:00:00:00':
       write_files:
diff --git a/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml b/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml
index 406e896..1af557e 100644
--- a/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml
+++ b/de/heat-templates/fragments/SrvInstancesVMCephOSD.yaml
@@ -91,6 +91,12 @@
       # Don't mount ephemeral0 to /mnt as it's by default
       mounts:
         - [ ephemeral0, null ]
+  huge_pages:
+    description: >
+      String formatted as '<Number of Gb for 1Gb huge pages>,<Number of Mb for 2Mb huge pages'
+      If number is equal to 0 alloacation of huge pages won't be configured.
+    default: '0,0'
+    type: string
 
 conditions:
   create_tf_data_network_res:
@@ -128,6 +134,7 @@
             $ironic_baremetal_network_cidr: { get_param: ironic_baremetal_network_cidr }
             $ironic_baremetal_tunnel_cidr: { get_param: ironic_baremetal_tunnel_cidr }
             $ironic_mt_enabled: { get_param: ironic_mt_enabled }
+            $huge_pages: { get_param: huge_pages }
 
   inject_files:
     type: "OS::Heat::CloudConfig"
diff --git a/de/heat-templates/scripts/instance_boot.sh b/de/heat-templates/scripts/instance_boot.sh
index b8f1293..1952d2b 100644
--- a/de/heat-templates/scripts/instance_boot.sh
+++ b/de/heat-templates/scripts/instance_boot.sh
@@ -34,6 +34,7 @@
 IRONIC_MT_ENABLED=$ironic_mt_enabled
 IRONIC_BAREMETAL_NETWORK_PREFIX=$(sed 's/[0-9]*\/[0-9]*$//' <<< $IRONIC_BAREMETAL_NETWORK)
 IRONIC_BAREMETAL_TUNNEL_NETWORK_PREFIX=$(sed 's/[0-9]*\/[0-9]*$//' <<< $IRONIC_BAREMETAL_TUNNEL_NETWORK)
+HUGE_PAGES=$huge_pages
 #
 # End of block
 #
@@ -66,7 +67,12 @@
 NTP_SERVERS=${NTP_SERVERS:-"ldap.scc.mirantis.net ldap.bud.mirantis.net"}
 DEFAULT_INTERFACE=$(ip route show default | awk '{print $5}')
 IRONIC_BAREMETAL_VXLAN_INTERFACE='vxlan10'
-
+HUGE_PAGES_1G_SIZE=$(echo "${HUGE_PAGES}" | awk -F ',' '{print $1}')
+HUGE_PAGES_2Mb_SIZE=$(echo "${HUGE_PAGES}" | awk -F ',' '{print $2}')
+CONFIGURE_HUGE_PAGES=false
+if [[ "${HUGE_PAGES_1G_SIZE}" -gt 0 ]] || [[ "${HUGE_PAGES_2Mb_SIZE}" -gt 0 ]]; then
+    CONFIGURE_HUGE_PAGES=true
+fi
 
 function retry {
     local retries=$1
@@ -558,6 +564,32 @@
 
 }
 
+function configure_huge_pages {
+    local nr_2Mb
+    local nr_1G
+    local apply_grub=false
+
+    if [[ ! $(cat /etc/default/grub | grep -E ^GRUB_CMDLINE_LINUX=".*hugepagesz=2M.*") ]] && [[ "${HUGE_PAGES_2Mb_SIZE}" -gt 0 ]]; then
+        nr_2Mb=$(( "${HUGE_PAGES_2Mb_SIZE}" / 2 ))
+        echo "Configure GRUB kernel cmd to allocate ${nr_2Mb} 2Mb huge pages"
+        echo "GRUB_CMDLINE_LINUX=\"\$GRUB_CMDLINE_LINUX hugepagesz=2M hugepages=$nr_2Mb\"" >> /etc/default/grub
+        apply_grub=true
+    fi
+
+    if [[ ! $(cat /etc/default/grub | grep -E ^GRUB_CMDLINE_LINUX=".*hugepagesz=1G.*") ]] && [[ "${HUGE_PAGES_1G_SIZE}" -gt 0 ]]; then
+        echo "Configure GRUB kernel cmd to allocate ${HUGE_PAGES_1G_SIZE} 1G huge pages"
+        echo "GRUB_CMDLINE_LINUX=\"\$GRUB_CMDLINE_LINUX hugepagesz=1G hugepages=${HUGE_PAGES_1G_SIZE}\"" >> /etc/default/grub
+        apply_grub=true
+    fi
+
+    if [[ "${apply_grub}" == true ]]; then
+        update-grub
+        cloud-init clean -r
+    else
+        echo "GRUB already configured with huge pages"
+    fi
+}
+
 case "$NODE_TYPE" in
     # Please keep the "prepare_metadata_files", "disable-rp-filter", "network_config" and "prepare_network" functions
     # at the very beginning in the same order.
@@ -608,6 +640,9 @@
         disable_iptables_for_bridges
         ;;
     worker)
+        if [[ "${CONFIGURE_HUGE_PAGES}" == true ]]; then
+            configure_huge_pages
+        fi
         nested_virt_config
         prepare_metadata_files
         disable_rp_filter
diff --git a/de/heat-templates/top.yaml b/de/heat-templates/top.yaml
index 1dbc91c..eb4ebf5 100644
--- a/de/heat-templates/top.yaml
+++ b/de/heat-templates/top.yaml
@@ -255,6 +255,12 @@
     description: The content of lab metadata.
     default: ''
     type: string
+  huge_pages:
+    description: >
+      String formatted as '<Number of Gb for 1Gb huge pages>,<Number of Mb for 2Mb huge pages'
+      If number is equal to 0 alloacation of huge pages won't be configured.
+    default: '0,0'
+    type: string
 
 conditions:
   create_tf_data_network_res:
@@ -497,6 +503,7 @@
           tf_data_network: {if: ["create_tf_data_network_res", { get_attr: [tf_data_network, tf_data_network_id] }, ""]}
           tf_data_subnet_id: {if: ["create_tf_data_network_res", { get_attr: [tf_data_network, tf_data_subnet_id] }, ""]}
           hardware_metadata: { get_param: hardware_metadata}
+          huge_pages: { get_param: huge_pages }
 
   gtws:
     type: OS::Heat::ResourceGroup