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
This commit is contained in:
Joshua Boniface 2021-09-13 01:46:53 -04:00
parent 1855d03a36
commit 6e0d0e264e
1 changed files with 21 additions and 0 deletions

View File

@ -196,6 +196,16 @@ def define_vm(zkhandler, config_data, target_node, node_limit, node_selector, no
if not valid_node: if not valid_node:
return False, 'ERROR: Specified node "{}" is invalid.'.format(target_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 # If a SR-IOV network device is being added, set its used state
dnetworks = common.getDomainNetworks(parsed_xml, {}) dnetworks = common.getDomainNetworks(parsed_xml, {})
for network in dnetworks: 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_parsed_xml = lxml.objectify.fromstring(old_vm_config)
old_dnetworks = common.getDomainNetworks(old_parsed_xml, {}) 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 # If a SR-IOV network device is being added, set its used state
dnetworks = common.getDomainNetworks(parsed_xml, {}) dnetworks = common.getDomainNetworks(parsed_xml, {})
for network in dnetworks: for network in dnetworks: