From 58db5370936e9acdda1cb328fc7cc73cf2bced6b Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Mon, 13 Sep 2021 01:46:53 -0400 Subject: [PATCH] Add memory and vCPU checks to VM define/modify Ensures that a VM won't: (a) Have provisioned more RAM than there is available on a given node. Due to memory overprovisioning, this is simply a "is the VM memory count more than the node count", and doesn't factor in free or used memory on a node, total cluster usage, etc. So if a node has 64GB total RAM, the VM limit is 64GB. It is up to an administrator to ensure sanity *below* that value. (b) Have provisioned more vCPUs than there are CPU cores on the node, minus 2 to account for hypervisor/storage processes. Will ensure there is no severe CPU contention caused by a single VM having more vCPUs than there are actual execution threads available. Closes #139 --- daemon-common/vm.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/daemon-common/vm.py b/daemon-common/vm.py index 5b6cf889..56ce03dd 100644 --- a/daemon-common/vm.py +++ b/daemon-common/vm.py @@ -196,6 +196,16 @@ def define_vm(zkhandler, config_data, target_node, node_limit, node_selector, no if not valid_node: return False, 'ERROR: Specified node "{}" is invalid.'.format(target_node) + # Validate the new RAM against the current active node + node_total_memory = int(zkhandler.read(('node.memory.total', target_node))) + if int(parsed_xml.memory.text) >= node_total_memory: + return False, 'ERROR: VM configuration specifies more memory ({} MiB) than node "{}" has available ({} MiB).'.format(parsed_xml.memory.text, target_node, node_total_memory) + + # Validate the number of vCPUs against the current active node + node_total_cpus = int(zkhandler.read(('node.data.static', target_node)).split()[0]) + if (node_total_cpus - 2) <= int(parsed_xml.vcpu.text): + return False, 'ERROR: VM configuration specifies more vCPUs ({}) than node "{}" has available ({} minus 2).'.format(parsed_xml.vcpu.text, target_node, node_total_cpus) + # If a SR-IOV network device is being added, set its used state dnetworks = common.getDomainNetworks(parsed_xml, {}) for network in dnetworks: @@ -429,6 +439,17 @@ def modify_vm(zkhandler, domain, restart, new_vm_config): old_parsed_xml = lxml.objectify.fromstring(old_vm_config) old_dnetworks = common.getDomainNetworks(old_parsed_xml, {}) + # Validate the new RAM against the current active node + node_name = zkhandler.read(('domain.node', dom_uuid)) + node_total_memory = int(zkhandler.read(('node.memory.total', node_name))) + if int(parsed_xml.memory.text) >= node_total_memory: + return False, 'ERROR: Updated VM configuration specifies more memory ({} MiB) than node "{}" has available ({} MiB).'.format(parsed_xml.memory.text, node_name, node_total_memory) + + # Validate the number of vCPUs against the current active node + node_total_cpus = int(zkhandler.read(('node.data.static', node_name)).split()[0]) + if (node_total_cpus - 2) <= int(parsed_xml.vcpu.text): + return False, 'ERROR: Updated VM configuration specifies more vCPUs ({}) than node "{}" has available ({} minus 2).'.format(parsed_xml.vcpu.text, node_name, node_total_cpus) + # If a SR-IOV network device is being added, set its used state dnetworks = common.getDomainNetworks(parsed_xml, {}) for network in dnetworks: