[Kimchi-devel] [PATCH] Multiple changes in guest maxMemory management
Paulo Vital
pvital at linux.vnet.ibm.com
Tue Dec 8 17:57:54 UTC 2015
Reviewed-by: Paulo Vital <pvital at linux.vnet.ibm.com>
On 12/08/2015 02:15 PM, Rodrigo Trujillo wrote:
> This patch includes 3 changes:
> - Set max_memory limit to 1TB
> - Set max_memory to 4*Memory
> - Set memory "hard_limit" tag to (maxMemory + 1Gib)
>
> All changes are related to issues found with memory in PCI passthrough
> or during Live Migration tests.
>
> Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo at linux.vnet.ibm.com>
> ---
> model/vms.py | 98 ++++++++++++++++++++++++++++++++++-------------------------
> osinfo.py | 11 ++++++-
> vmtemplate.py | 13 ++++++++
> 3 files changed, 79 insertions(+), 43 deletions(-)
>
> diff --git a/model/vms.py b/model/vms.py
> index 4835adb..47dd0ce 100644
> --- a/model/vms.py
> +++ b/model/vms.py
> @@ -57,6 +57,7 @@ from wok.plugins.kimchi.model.utils import get_ascii_nonascii_name, get_vm_name
> from wok.plugins.kimchi.model.utils import get_metadata_node
> from wok.plugins.kimchi.model.utils import remove_metadata_node
> from wok.plugins.kimchi.model.utils import set_metadata_node
> +from wok.plugins.kimchi.osinfo import MAX_MEM_LIM
> from wok.plugins.kimchi.screenshot import VMScreenshot
> from wok.plugins.kimchi.utils import template_name_from_uri
> from wok.plugins.kimchi.xmlutils.cpu import get_cpu_xml, get_numa_xml
> @@ -881,49 +882,62 @@ class VMModel(object):
> else:
> if memory is not None:
> root.remove(memory)
> +
> + def _get_slots(maxMem):
> + slots = (maxMem - params['memory']) >> 10
> + # Libvirt does not accepts slots <= 1
> + if slots < 0:
> + raise OperationFailed("KCHVM0041E")
> + elif slots == 0:
> + slots = 1
> +
> + distro, _, _ = platform.linux_distribution()
> + if distro == "IBM_PowerKVM":
> + # max 32 slots on Power
> + if slots > 32:
> + slots = 32
> + return slots
> + # End of _get_slots
> +
> + def _get_newMaxMem():
> + # Setting max memory to 4x memory requested, host total memory,
> + # or 1 TB. This should avoid problems with live migration
> + newMaxMem = MAX_MEM_LIM
> + hostMem = self.conn.get().getInfo()[1] << 10
> + if hostMem < newMaxMem:
> + newMaxMem = hostMem
> + mem = params.get('memory', 0)
> + if (mem != 0) and (((mem * 4) << 10) < newMaxMem):
> + newMaxMem = (mem * 4) << 10
> +
> + distro, _, _ = platform.linux_distribution()
> + if distro == "IBM_PowerKVM":
> + # max memory 256MiB alignment
> + newMaxMem -= (newMaxMem % 256)
> + return newMaxMem
> +
> maxMem = root.find('.maxMemory')
> - host_mem = self.conn.get().getInfo()[1]
> - slots = (host_mem - params['memory']) >> 10
> - # Libvirt does not accepts slots <= 1
> - if slots < 0:
> - raise OperationFailed("KCHVM0041E")
> - elif slots == 0:
> - slots = 1
> -
> - force_max_mem_update = False
> - distro, _, _ = platform.linux_distribution()
> - if distro == "IBM_PowerKVM":
> - # max memory 256MiB alignment
> - host_mem -= (host_mem % PPC_MEM_ALIGN)
> - # force max memory update if it exists but it's wrong.
> - if maxMem is not None and\
> - int(maxMem.text) != (host_mem << 10):
> - force_max_mem_update = True
> -
> - # max 32 slots on Power
> - if slots > 32:
> - slots = 32
> -
> - if maxMem is None:
> - max_mem_xml = E.maxMemory(
> - str(host_mem << 10),
> - unit='Kib',
> - slots=str(slots))
> - root.insert(0, max_mem_xml)
> - new_xml = ET.tostring(root, encoding="utf-8")
> - else:
> - # Update slots only
> - new_xml = xml_item_update(ET.tostring(root, encoding="utf-8"),
> - './maxMemory',
> - str(slots),
> - attr='slots')
> -
> - if force_max_mem_update:
> - new_xml = xml_item_update(new_xml,
> - './maxMemory',
> - str(host_mem << 10))
> -
> - return new_xml
> + if maxMem is not None:
> + root.remove(maxMem)
> +
> + # Setting maxMemory
> + newMaxMem = _get_newMaxMem()
> + slots = _get_slots(newMaxMem >> 10)
> + max_mem_xml = E.maxMemory(
> + str(newMaxMem),
> + unit='Kib',
> + slots=str(slots))
> + root.insert(0, max_mem_xml)
> +
> + # Setting memory hard limit to max_memory + 1GiB
> + memtune = root.find('memtune')
> + if memtune is not None:
> + hl = memtune.find('hard_limit')
> + if hl is not None:
> + memtune.remove(hl)
> + memtune.insert(0, E.hard_limit(str(newMaxMem + 1048576),
> + unit='Kib'))
> +
> return ET.tostring(root, encoding="utf-8")
>
> def _get_host_maxcpu(self):
> diff --git a/osinfo.py b/osinfo.py
> index 1891398..33757a3 100644
> --- a/osinfo.py
> +++ b/osinfo.py
> @@ -88,6 +88,9 @@ modern_version_bases = {'x86': {'debian': '6.0', 'ubuntu': '7.10',
> icon_available_distros = [icon[5:-4] for icon in glob.glob1('%s/images/'
> % PluginPaths('kimchi').ui_dir, 'icon-*.png')]
>
> +# Max memory 1TB, in KiB
> +MAX_MEM_LIM = 1073741824
> +
>
> def _get_arch():
> for arch, sub_archs in SUPPORTED_ARCHS.iteritems():
> @@ -199,7 +202,9 @@ def lookup(distro, version):
> params['os_version'] = version
> arch = _get_arch()
>
> - # Setting maxMemory of the VM, which will be equal total Host memory in Kib
> + # Setting maxMemory of the VM, which will be lesser value between:
> + # [ 1TB, (Template Memory * 4), Host Physical Memory.
> + # Here, we return 1TB or aligned Host Physical Memory
> if hasattr(psutil, 'virtual_memory'):
> params['max_memory'] = psutil.virtual_memory().total >> 10
> else:
> @@ -212,6 +217,10 @@ def lookup(distro, version):
> alignment = params['max_memory'] % (PPC_MEM_ALIGN << 10)
> params['max_memory'] -= alignment
>
> + # Setting limit to 1TB
> + if params['max_memory'] > MAX_MEM_LIM:
> + params['max_memory'] = MAX_MEM_LIM
> +
> if distro in modern_version_bases[arch]:
> if LooseVersion(version) >= LooseVersion(
> modern_version_bases[arch][distro]):
> diff --git a/vmtemplate.py b/vmtemplate.py
> index b90f221..b6e9431 100644
> --- a/vmtemplate.py
> +++ b/vmtemplate.py
> @@ -352,6 +352,13 @@ class VMTemplate(object):
> else:
> params['cdroms'] = cdrom_xml
>
> + # In order to avoid problems with live migration, setting maxMemory of
> + # the VM, which will be lesser value between:
> + # [ 1TB, (Template Memory * 4), Host Physical Memory.
> + tmp_max_mem = (params['memory'] << 10) * 4
> + if tmp_max_mem < params['max_memory']:
> + params['max_memory'] = tmp_max_mem
> +
> # Setting maximum number of slots to avoid errors when hotplug memory
> # Number of slots are the numbers of chunks of 1GB that fit inside
> # the max_memory of the host minus memory assigned to the VM. It
> @@ -367,6 +374,9 @@ class VMTemplate(object):
> if distro == "IBM_PowerKVM":
> params['slots'] = 32
>
> + # set a hard limit using max_memory + 1GiB
> + params['hard_limit'] = params['max_memory'] + (1024 << 10)
> +
> cpu_topo = self.info.get('cpu_info').get('topology')
> if (cpu_topo is not None):
> sockets = int(max_vcpus / (cpu_topo['cores'] *
> @@ -390,6 +400,9 @@ class VMTemplate(object):
> %(qemu-stream-cmdline)s
> <name>%(name)s</name>
> <uuid>%(uuid)s</uuid>
> + <memtune>
> + <hard_limit unit='KiB'>%(hard_limit)s</hard_limit>
> + </memtune>
> <maxMemory slots='%(slots)s' unit='KiB'>%(max_memory)s</maxMemory>
> <memory unit='MiB'>%(memory)s</memory>
> %(vcpus)s
>
More information about the Kimchi-devel
mailing list