This patch removes the restriction of only allow 32 memory devices
of 1GB. Now, Kimchi is going to add an unique memory device with the
amount of memory to be increased (per request).
Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo(a)linux.vnet.ibm.com>
---
i18n.py | 3 +--
model/vms.py | 81 ++++++++++++++++++++++++++----------------------------------
2 files changed, 36 insertions(+), 48 deletions(-)
diff --git a/i18n.py b/i18n.py
index 2301e60..9f40298 100644
--- a/i18n.py
+++ b/i18n.py
@@ -97,8 +97,7 @@ messages = {
"KCHVM0041E": _("Memory assigned is higher then the maximum allowed in
the host: %(maxmem)sMib."),
"KCHVM0042E": _("Guest '%(name)s' does not support live memory
update. Please, with the guest offline, set Maximum Memory with a value greater then
Memory 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"),
- "KCHVM0045E": _("There are not enough free slots of 1024 Mib in the
guest."),
+ "KCHVM0045E": _("There are not enough free slots to add a new memory
device."),
"KCHVM0046E": _("Host's libvirt or qemu version does not support
memory devices and memory hotplug. Libvirt must be >= 1.2.14 and QEMU must be >=
2.1."),
"KCHVM0047E": _("Error attaching memory device. Details:
%(error)s"),
"KCHVM0048E": _("Cannot start %(name)s. Virtual machine is already
running."),
diff --git a/model/vms.py b/model/vms.py
index ef53e38..ae77d3d 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -971,6 +971,15 @@ class VMModel(object):
dom.isActive()):
self._update_memory_live(dom, params)
+ def _get_mem_dev_total_size(self, xml):
+ root = ET.fromstring(xml)
+ totMemDevs = 0
+ for size in root.findall('./devices/memory/target/size'):
+ totMemDevs += convert_data_size(size.text,
+ size.get('unit'),
+ 'MiB')
+ return totMemDevs
+
def _update_memory_live(self, dom, params):
# Check if host supports memory device
if not self.caps.mem_hotplug_support:
@@ -979,56 +988,42 @@ class VMModel(object):
xml = dom.XMLDesc(0)
max_mem = xpath_get_text(xml, './maxMemory')
if max_mem == []:
- raise OperationFailed('KCHVM0042E', {'name': dom.name()})
+ raise InvalidOperation('KCHVM0042E', {'name': dom.name()})
- # Memory live update must be done in chunks of 1024 Mib or 1Gib
new_mem = params['memory']['current']
old_mem = int(xpath_get_text(xml, XPATH_DOMAIN_MEMORY)[0]) >> 10
- if new_mem < old_mem:
- raise OperationFailed('KCHVM0043E')
- if (new_mem - old_mem) % 1024 != 0:
- raise OperationFailed('KCHVM0044E')
+ memory = new_mem - old_mem
+ flags = libvirt.VIR_DOMAIN_MEM_CONFIG | libvirt.VIR_DOMAIN_MEM_LIVE
- # make sure memory is alingned in 256MiB in PowerPC
distro, _, _ = platform.linux_distribution()
- if (distro == "IBM_PowerKVM" and new_mem % PPC_MEM_ALIGN != 0):
- raise InvalidParameter('KCHVM0071E',
- {'param': "Memory",
- 'mem': str(new_mem),
- 'alignment': str(PPC_MEM_ALIGN)})
-
- # Check slot spaces:
- total_slots = int(xpath_get_text(xml, './maxMemory/@slots')[0])
- needed_slots = (new_mem - old_mem) >> 10
- used_slots = len(xpath_get_text(xml, './devices/memory'))
- if needed_slots > (total_slots - used_slots):
- raise OperationFailed('KCHVM0045E')
- elif needed_slots == 0:
- # New memory value is same that current memory set
+ if distro == "IBM_PowerKVM":
+ # make sure memory is alingned in 256MiB in PowerPC
+ if (new_mem % PPC_MEM_ALIGN != 0):
+ raise InvalidParameter('KCHVM0071E',
+ {'param': "Memory",
+ 'mem': str(new_mem),
+ 'alignment': str(PPC_MEM_ALIGN)})
+ # PPC suports only 32 memory slots
+ if len(xpath_get_text(xml, './devices/memory')) == 32:
+ raise InvalidOperation('KCHVM0045E')
+
+ if memory == 0:
+ # Nothing to do
return
+ if memory < 0:
+ raise InvalidOperation('KCHVM0043E')
- distro, _, _ = platform.linux_distribution()
- if distro == "IBM_PowerKVM" and needed_slots > 32:
- raise OperationFailed('KCHVM0045E')
-
- # Finally, we are ok to hot add the memory devices
+ # Finally HotPlug operation ( memory > 0 )
try:
- self._hot_add_memory_devices(dom, needed_slots)
+ # Create memory device xml
+ tmp_xml = E.memory(E.target(E.size(str(memory),
+ unit='MiB')), model='dimm')
+ if has_cpu_numa(dom):
+ tmp_xml.find('target').append(E.node('0'))
+ dom.attachDeviceFlags(etree.tostring(tmp_xml), flags)
except Exception as e:
raise OperationFailed("KCHVM0047E", {'error': e.message})
- def _hot_add_memory_devices(self, dom, amount):
- # Hot add given number of memory devices in the guest
- flags = libvirt.VIR_DOMAIN_MEM_CONFIG | libvirt.VIR_DOMAIN_MEM_LIVE
- # Create memory device xml
- tmp_xml = E.memory(E.target(E.size('1', unit='GiB')),
model='dimm')
- if has_cpu_numa(dom):
- tmp_xml.find('target').append(E.node('0'))
- mem_dev_xml = etree.tostring(tmp_xml)
- # Add chunks of 1G of memory
- for i in range(amount):
- dom.attachDeviceFlags(mem_dev_xml, flags)
-
def _has_video(self, dom):
dom = ElementTree.fromstring(dom.XMLDesc(0))
return dom.find('devices/video') is not None
@@ -1217,13 +1212,7 @@ class VMModel(object):
memory = dom.maxMemory() >> 10
curr_mem = (info[2] >> 10)
if memory != curr_mem:
- root = ET.fromstring(xml)
- totMemDevs = 0
- for size in root.findall('./devices/memory/target/size'):
- totMemDevs += convert_data_size(size.text,
- size.get('unit'),
- 'MiB')
- memory = curr_mem + totMemDevs
+ memory = curr_mem + self._get_mem_dev_total_size(xml)
# assure there is no zombie process left
for proc in self._serial_procs[:]:
--
2.1.0