Merge "Derive HCI reseverved host memory without average guest workload"

This commit is contained in:
Zuul 2020-09-10 01:03:30 +00:00 committed by Gerrit Code Review
commit 9cdc0a5b41
2 changed files with 71 additions and 36 deletions

View File

@ -48,12 +48,14 @@ options:
type: map type: map
average_guest_cpu_utilization_percentage: average_guest_cpu_utilization_percentage:
description: Percentage of CPU utilization expected for average guest, e.g. 99 means 99% and 10 means 10% description: Percentage of CPU utilization expected for average guest, e.g. 99 means 99% and 10 means 10%
required: True required: False
type: int type: int
default: 0
average_guest_memory_size_in_mb: average_guest_memory_size_in_mb:
description: Amount of memory in MB required by the average guest description: Amount of memory in MB required by the average guest
required: True required: False
type: int type: int
default: 0
derived_parameters: derived_parameters:
description: any previously derived parameters which should be included in the final result description: any previously derived parameters which should be included in the final result
required: False required: False
@ -113,11 +115,13 @@ derived_parameters:
MB_PER_GB = 1024 MB_PER_GB = 1024
def derive(mem_gb, vcpus, osds, average_guest_memory_size_in_mb, def derive(mem_gb, vcpus, osds, average_guest_memory_size_in_mb=0,
average_guest_cpu_utilization_percentage, average_guest_cpu_utilization_percentage=0,
mem_gb_per_osd=5, vcpus_per_osd=1.0, total_memory_threshold=0.8): mem_gb_per_osd=5, vcpus_per_osd=1.0, total_memory_threshold=0.8):
""" """
Determines the recommended Nova scheduler values based on Ceph needs. Determines the recommended Nova scheduler values based on Ceph needs
and described average Nova guest workload in CPU and Memory utilization.
If expected guest utilization is not provided result is less accurate.
Returns dictionary containing the keys: cpu_allocation_ratio (float), Returns dictionary containing the keys: cpu_allocation_ratio (float),
nova_reserved_mem_mb (int), message (string), failed (boolean). nova_reserved_mem_mb (int), message (string), failed (boolean).
""" """
@ -128,6 +132,12 @@ def derive(mem_gb, vcpus, osds, average_guest_memory_size_in_mb,
derived['message'] = "" derived['message'] = ""
derived['failed'] = False derived['failed'] = False
if average_guest_memory_size_in_mb == 0 and \
average_guest_cpu_utilization_percentage == 0:
workload = False
else:
workload = True
# catch possible errors in parameters # catch possible errors in parameters
if mem_gb < 1: if mem_gb < 1:
msg = "Unable to determine the amount of physical memory " msg = "Unable to determine the amount of physical memory "
@ -147,13 +157,13 @@ def derive(mem_gb, vcpus, osds, average_guest_memory_size_in_mb,
derived['message'] += msg + "\n" derived['message'] += msg + "\n"
derived['failed'] = True derived['failed'] = True
if average_guest_memory_size_in_mb < 0: if average_guest_memory_size_in_mb < 0 and workload:
msg = "The average_guest_memory_size_in_mb must be a positive integer." msg = "If average_guest_memory_size_in_mb is used it must be greater than 0"
derived['message'] += msg + "\n" derived['message'] += msg + "\n"
derived['failed'] = True derived['failed'] = True
if average_guest_cpu_utilization_percentage < 0: if average_guest_cpu_utilization_percentage < 0 and workload:
msg = "The average_guest_cpu_utilization_percentage must be a positive integer." msg = "If average_guest_cpu_utilization_percentage is used it must be greater than 0"
derived['message'] += msg + "\n" derived['message'] += msg + "\n"
derived['failed'] = True derived['failed'] = True
@ -169,19 +179,23 @@ def derive(mem_gb, vcpus, osds, average_guest_memory_size_in_mb,
return derived return derived
# perform the calculation # perform the calculation
average_guest_size = average_guest_memory_size_in_mb / float(MB_PER_GB) if workload:
average_guest_util = average_guest_cpu_utilization_percentage * 0.01 average_guest_size = average_guest_memory_size_in_mb / float(MB_PER_GB)
number_of_guests = int(left_over_mem average_guest_util = average_guest_cpu_utilization_percentage * 0.01
/ (average_guest_size + gb_overhead_per_guest)) number_of_guests = int(left_over_mem
nova_reserved_mem_mb = MB_PER_GB * ((mem_gb_per_osd * osds) / (average_guest_size + gb_overhead_per_guest))
+ (number_of_guests * gb_overhead_per_guest)) nova_reserved_mem_mb = MB_PER_GB * ((mem_gb_per_osd * osds)
nonceph_vcpus = vcpus - (vcpus_per_osd * osds) + (number_of_guests * gb_overhead_per_guest))
guest_vcpus = nonceph_vcpus / average_guest_util nonceph_vcpus = vcpus - (vcpus_per_osd * osds)
cpu_allocation_ratio = guest_vcpus / vcpus guest_vcpus = nonceph_vcpus / average_guest_util
cpu_allocation_ratio = guest_vcpus / vcpus
else:
nova_reserved_mem_mb = MB_PER_GB * (mem_gb_per_osd * osds)
# save calculation results # save calculation results
derived['cpu_allocation_ratio'] = cpu_allocation_ratio
derived['nova_reserved_mem_mb'] = int(nova_reserved_mem_mb) derived['nova_reserved_mem_mb'] = int(nova_reserved_mem_mb)
if workload:
derived['cpu_allocation_ratio'] = cpu_allocation_ratio
# capture derivation details in message # capture derivation details in message
msg = "Derived Parameters results" msg = "Derived Parameters results"
@ -189,29 +203,41 @@ def derive(mem_gb, vcpus, osds, average_guest_memory_size_in_mb,
msg += "\n - Total host RAM in GB: %d" % mem_gb msg += "\n - Total host RAM in GB: %d" % mem_gb
msg += "\n - Total host vCPUs: %d" % vcpus msg += "\n - Total host vCPUs: %d" % vcpus
msg += "\n - Ceph OSDs per host: %d" % osds msg += "\n - Ceph OSDs per host: %d" % osds
msg += "\n - Average guest memory size in GB: %d" % average_guest_size if workload:
msg += "\n - Average guest CPU utilization: %.0f%%" % \ msg += "\n - Average guest memory size in GB: %d" % average_guest_size
average_guest_cpu_utilization_percentage msg += "\n - Average guest CPU utilization: %.0f%%" % \
average_guest_cpu_utilization_percentage
msg += "\n " msg += "\n "
msg += "\n Outputs:" msg += "\n Outputs:"
msg += "\n - number of guests allowed based on memory = %d" % number_of_guests if workload:
msg += "\n - number of guest vCPUs allowed = %d" % int(guest_vcpus) msg += "\n - number of guests allowed based on memory = %d" % number_of_guests
msg += "\n - number of guest vCPUs allowed = %d" % int(guest_vcpus)
msg += "\n - nova.conf cpu_allocation_ratio = %2.2f" % cpu_allocation_ratio
msg += "\n - nova.conf reserved_host_memory = %d MB" % nova_reserved_mem_mb msg += "\n - nova.conf reserved_host_memory = %d MB" % nova_reserved_mem_mb
msg += "\n - nova.conf cpu_allocation_ratio = %2.2f" % cpu_allocation_ratio
msg += "\n "
msg += "\nCompare \"guest vCPUs allowed\" to \"guests allowed based on memory\""
msg += "\nfor actual guest count."
msg += "\n " msg += "\n "
if workload:
msg += "\nCompare \"guest vCPUs allowed\" to \"guests allowed based on memory\""
msg += "\nfor actual guest count."
msg += "\n "
warning_msg = "" warning_msg = ""
if nova_reserved_mem_mb > (MB_PER_GB * mem_gb * total_memory_threshold): if nova_reserved_mem_mb > (MB_PER_GB * mem_gb * total_memory_threshold):
warning_msg += "ERROR: %d GB is not enough memory to run hyperconverged\n" % mem_gb warning_msg += "ERROR: %d GB is not enough memory to run hyperconverged\n" % mem_gb
derived['failed'] = True derived['failed'] = True
if cpu_allocation_ratio < 0.5: if workload:
warning_msg += "ERROR: %d is not enough vCPU to run hyperconverged\n" % vcpus if cpu_allocation_ratio < 0.5:
derived['failed'] = True warning_msg += "ERROR: %d is not enough vCPU to run hyperconverged\n" % vcpus
if cpu_allocation_ratio > 16.0: derived['failed'] = True
warning_msg += "WARNING: do not increase vCPU overcommit ratio beyond 16:1\n" if cpu_allocation_ratio > 16.0:
warning_msg += "WARNING: do not increase vCPU overcommit ratio beyond 16:1\n"
else:
warning_msg += "WARNING: the average guest workload was not provided. \n"
warning_msg += "Both average_guest_cpu_utilization_percentage and \n"
warning_msg += "average_guest_memory_size_in_mb are defaulted to 0. \n"
warning_msg += "The HCI derived parameter calculation cannot set the \n"
warning_msg += "Nova cpu_allocation_ratio. The Nova reserved_host_memory_mb \n"
warning_msg += "will be set based on the number of OSDs but the Nova \n"
warning_msg += "guest memory overhead will not be taken into account. \n"
derived['message'] = warning_msg + msg derived['message'] = warning_msg + msg
return derived return derived
@ -422,8 +448,8 @@ def main():
tripleo_environment_parameters=dict(type=dict, required=True), tripleo_environment_parameters=dict(type=dict, required=True),
tripleo_role_name=dict(type=str, required=True), tripleo_role_name=dict(type=str, required=True),
introspection_data=dict(type=dict, required=True), introspection_data=dict(type=dict, required=True),
average_guest_cpu_utilization_percentage=dict(type=int, required=True), average_guest_cpu_utilization_percentage=dict(type=int, required=False, default=0),
average_guest_memory_size_in_mb=dict(type=int, required=True), average_guest_memory_size_in_mb=dict(type=int, required=False, default=0),
derived_parameters=dict(type=dict, required=False), derived_parameters=dict(type=dict, required=False),
new_heat_environment_path=dict(type=str, required=False), new_heat_environment_path=dict(type=str, required=False),
report_path=dict(type=str, required=False), report_path=dict(type=str, required=False),
@ -465,7 +491,8 @@ def main():
if not derivation['failed']: if not derivation['failed']:
role_derivation = {} role_derivation = {}
role_derivation['NovaReservedHostMemory'] = derivation['nova_reserved_mem_mb'] role_derivation['NovaReservedHostMemory'] = derivation['nova_reserved_mem_mb']
role_derivation['NovaCPUAllocationRatio'] = derivation['cpu_allocation_ratio'] if 'cpu_allocation_ratio' in derivation:
role_derivation['NovaCPUAllocationRatio'] = derivation['cpu_allocation_ratio']
role_name_parameters = module.params['tripleo_role_name'] + 'Parameters' role_name_parameters = module.params['tripleo_role_name'] + 'Parameters'
existing_params[role_name_parameters] = role_derivation existing_params[role_name_parameters] = role_derivation
# write out to file if requested # write out to file if requested

View File

@ -153,3 +153,11 @@ class TestTripleoDeriveHciParameters(tests_base.TestCase):
self.assertEqual(vcpu_ratio, ratio_map[flavor]) self.assertEqual(vcpu_ratio, ratio_map[flavor])
self.assertIsNotNone(vcpu_msg) self.assertIsNotNone(vcpu_msg)
self.assertFalse(vcpu_warn) self.assertFalse(vcpu_warn)
def test_derive_without_workload(self):
"""Test the derive method without passing the expected average
guest cpu and mem utilization and confirm expected result
"""
der = derive_params.derive(mem_gb=256, vcpus=56, osds=16)
self.assertFalse(der['failed'])
self.assertEqual(der['nova_reserved_mem_mb'], 81920)