[PATCH 1/3][Kimchi] Issue #753: Remove max memory settings from osinfo.py

VmTemplates 'self.info' is not going to have the parameter 'max_memory', after remove max memory settings from osinfo. This way, max_memory will not be recorded in objectstore. Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo@linux.vnet.ibm.com> --- osinfo.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/osinfo.py b/osinfo.py index 33757a3..e6553a0 100644 --- a/osinfo.py +++ b/osinfo.py @@ -27,9 +27,6 @@ from distutils.version import LooseVersion from wok.config import PluginPaths -# In PowerPC, memories must be aligned to 256 MiB -PPC_MEM_ALIGN = 256 - SUPPORTED_ARCHS = {'x86': ('i386', 'i686', 'x86_64'), 'power': ('ppc', 'ppc64'), @@ -88,9 +85,6 @@ 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(): @@ -202,24 +196,9 @@ def lookup(distro, version): params['os_version'] = version arch = _get_arch() - # 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: - params['max_memory'] = psutil.TOTAL_PHYMEM >> 10 # set up arch to ppc64 instead of ppc64le due to libvirt compatibility if params["arch"] == "ppc64le": params["arch"] = "ppc64" - # in Power, memory must be aligned in 256MiB - if (params['max_memory'] >> 10) % PPC_MEM_ALIGN != 0: - 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( -- 2.1.0

When Kimchi creates a new template, it is recording the value of max_memory. This value is related to host and guest memory assigned or updated. If the value remains in objectstore, Kimchi will always use it, what is wrong, since host total memory or guest memory can change, and this should update max_memory value as well. This patch includes a new memory test during Template creation. An error will be raised if memory greater than max memory allowed. It also adds max memory settings to vmtemplate.py Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo@linux.vnet.ibm.com> --- i18n.py | 2 +- model/templates.py | 5 +++++ model/vms.py | 6 +++--- vmtemplate.py | 39 ++++++++++++++++++++++++++++++++------- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/i18n.py b/i18n.py index 96729ef..7c96d73 100644 --- a/i18n.py +++ b/i18n.py @@ -99,7 +99,7 @@ messages = { "KCHVM0038E": _("Unable to suspend VM '%(name)s'. Details: %(err)s"), "KCHVM0039E": _("Cannot resume VM '%(name)s' because it is not paused."), "KCHVM0040E": _("Unable to resume VM '%(name)s'. Details: %(err)s"), - "KCHVM0041E": _("Memory assigned is higher then the maximum allowed in the host."), + "KCHVM0041E": _("Memory assigned is higher then the maximum allowed in the host: %(maxmem)sMib."), "KCHVM0042E": _("VM '%(name)s' does not support live memory update. Update the memory with the machine offline to enable this feature."), "KCHVM0043E": _("Only increase memory is allowed in active VMs"), "KCHVM0044E": _("For live memory update, new memory value must be equal old memory value plus multiples of 1024 Mib"), diff --git a/model/templates.py b/model/templates.py index 84cdd02..c9b11c3 100644 --- a/model/templates.py +++ b/model/templates.py @@ -82,6 +82,11 @@ class TemplatesModel(object): # will be raised here t = LibvirtVMTemplate(params, scan=True, conn=self.conn) + # Validate max memory + maxMem = (t._get_max_memory(t.info.get('memory')) >> 10) + if t.info.get('memory') > maxMem: + raise OperationFailed("KCHVM0041E", {'maxmem': str(maxMem)}) + # Validate volumes for disk in t.info.get('disks'): volume = disk.get('volume') diff --git a/model/vms.py b/model/vms.py index 47dd0ce..3faee5a 100644 --- a/model/vms.py +++ b/model/vms.py @@ -48,7 +48,6 @@ from wok.plugins.kimchi import model from wok.plugins.kimchi import vnc from wok.plugins.kimchi.config import READONLY_POOL_TYPE, get_kimchi_version from wok.plugins.kimchi.kvmusertests import UserTests -from wok.plugins.kimchi.osinfo import PPC_MEM_ALIGN from wok.plugins.kimchi.model.config import CapabilitiesModel from wok.plugins.kimchi.model.cpuinfo import CPUInfoModel from wok.plugins.kimchi.model.featuretests import FeatureTests @@ -57,9 +56,9 @@ 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.vmtemplate import MAX_MEM_LIM, PPC_MEM_ALIGN from wok.plugins.kimchi.xmlutils.cpu import get_cpu_xml, get_numa_xml from wok.plugins.kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks @@ -887,7 +886,8 @@ class VMModel(object): slots = (maxMem - params['memory']) >> 10 # Libvirt does not accepts slots <= 1 if slots < 0: - raise OperationFailed("KCHVM0041E") + raise OperationFailed("KCHVM0041E", + {'maxmem': str(maxMem)}) elif slots == 0: slots = 1 diff --git a/vmtemplate.py b/vmtemplate.py index 5c6a8d8..d629226 100644 --- a/vmtemplate.py +++ b/vmtemplate.py @@ -19,6 +19,7 @@ import os import platform +import psutil import stat import time import urlparse @@ -41,6 +42,12 @@ from wok.plugins.kimchi.xmlutils.qemucmdline import get_qemucmdline_xml from wok.plugins.kimchi.xmlutils.serial import get_serial_xml +# In PowerPC, memories must be aligned to 256 MiB +PPC_MEM_ALIGN = 256 +# Max memory 1TB, in KiB +MAX_MEM_LIM = 1073741824 + + class VMTemplate(object): def __init__(self, args, scan=False): """ @@ -324,6 +331,27 @@ class VMTemplate(object): self.info.get('memory') << 10, cpu_topo) + def _get_max_memory(self, guest_memory): + # Setting maxMemory of the VM, which will be lesser value between: + # 1TB, (Template Memory * 4), Host Physical Memory. + max_memory = MAX_MEM_LIM + if hasattr(psutil, 'virtual_memory'): + host_memory = psutil.virtual_memory().total >> 10 + else: + host_memory = psutil.TOTAL_PHYMEM >> 10 + if host_memory < max_memory: + max_memory = host_memory + if (((guest_memory * 4) << 10) < max_memory): + max_memory = (guest_memory * 4) << 10 + + # set up arch to ppc64 instead of ppc64le due to libvirt compatibility + if self.info["arch"] == "ppc64": + # in Power, memory must be aligned in 256MiB + if (max_memory >> 10) % PPC_MEM_ALIGN != 0: + alignment = max_memory % (PPC_MEM_ALIGN << 10) + max_memory -= alignment + return max_memory + def to_vm_xml(self, vm_name, vm_uuid, **kwargs): params = dict(self.info) params['name'] = vm_name @@ -352,12 +380,8 @@ 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 + # max memory + params['max_memory'] = self._get_max_memory(params['memory']) # Setting maximum number of slots to avoid errors when hotplug memory # Number of slots are the numbers of chunks of 1GB that fit inside @@ -366,7 +390,8 @@ class VMTemplate(object): params['slots'] = ((params['max_memory'] >> 10) - params['memory']) >> 10 if params['slots'] < 0: - raise OperationFailed("KCHVM0041E") + raise OperationFailed("KCHVM0041E", + {'maxmem': str(params['max_memory'] >> 10)}) elif params['slots'] == 0: params['slots'] = 1 elif params['slots'] > 32: -- 2.1.0

This patch fixes some problems with max memory checkings and add 2 new tests. Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo@linux.vnet.ibm.com> --- tests/test_template.py | 13 +++++++++++++ tests/test_vmtemplate.py | 24 +++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/tests/test_template.py b/tests/test_template.py index 0cc5ac8..0b3dd98 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -20,6 +20,7 @@ import json import os +import psutil import unittest from functools import partial @@ -140,6 +141,18 @@ class TemplateTests(unittest.TestCase): ) self.assertEquals(tmpl['disks'][0]['format'], 'vmdk') + # Create template with memory higher than host max + if hasattr(psutil, 'virtual_memory'): + max_mem = (psutil.virtual_memory().total >> 10 >> 10) + else: + max_mem = (psutil.TOTAL_PHYMEM >> 10 >> 10) + memory = max_mem + 1024 + t = {'name': 'test-maxmem', 'cdrom': '/tmp/mock.iso', 'memory': memory} + req = json.dumps(t) + resp = self.request('/plugins/kimchi/templates', req, 'POST') + self.assertEquals(500, resp.status) + self.assertTrue(str(max_mem) in resp.read()) + def test_customized_tmpl(self): # Create a template t = {'name': 'test', 'cdrom': '/tmp/mock.iso'} diff --git a/tests/test_vmtemplate.py b/tests/test_vmtemplate.py index 79e3b52..de2d542 100644 --- a/tests/test_vmtemplate.py +++ b/tests/test_vmtemplate.py @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os +import psutil import unittest import uuid @@ -88,12 +89,7 @@ class VMTemplateTests(unittest.TestCase): def test_to_xml(self): graphics = {'type': 'spice', 'listen': '127.0.0.1'} vm_uuid = str(uuid.uuid4()).replace('-', '') - if os.uname()[4] in ['ppc', 'ppc64', 'ppc64le']: - maxmem = 3328 - else: - maxmem = 3072 - t = VMTemplate({'name': 'test-template', 'cdrom': self.iso, - 'max_memory': maxmem << 10}) + t = VMTemplate({'name': 'test-template', 'cdrom': self.iso}) xml = t.to_vm_xml('test-vm', vm_uuid, graphics=graphics) self.assertEquals(vm_uuid, xpath_get_text(xml, "/domain/uuid")[0]) self.assertEquals('test-vm', xpath_get_text(xml, "/domain/name")[0]) @@ -102,7 +98,21 @@ class VMTemplateTests(unittest.TestCase): expr = "/domain/devices/graphics/@listen" self.assertEquals(graphics['listen'], xpath_get_text(xml, expr)[0]) expr = "/domain/maxMemory/@slots" - self.assertEquals('2', xpath_get_text(xml, expr)[0]) + self.assertEquals('3', xpath_get_text(xml, expr)[0]) + expr = "/domain/maxMemory" + self.assertEquals(str((1024 * 4) << 10), xpath_get_text(xml, expr)[0]) + + if hasattr(psutil, 'virtual_memory'): + host_memory = psutil.virtual_memory().total >> 10 + else: + host_memory = psutil.TOTAL_PHYMEM >> 10 + t = VMTemplate({'name': 'test-template', 'cdrom': self.iso, + 'memory': (host_memory >> 10) - 512}) + xml = t.to_vm_xml('test-vm', vm_uuid, graphics=graphics) + expr = "/domain/maxMemory" + self.assertEquals(str(host_memory), xpath_get_text(xml, expr)[0]) + expr = "/domain/maxMemory/@slots" + self.assertEquals('1', xpath_get_text(xml, expr)[0]) def test_arg_merging(self): """ -- 2.1.0
participants (2)
-
Aline Manera
-
Rodrigo Trujillo