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(a)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