Change in vdsm[master]: virt: Memory hotunplug

vdelima at redhat.com vdelima at redhat.com
Thu May 21 15:32:03 UTC 2015


Vitor de Lima has uploaded a new change for review.

Change subject: virt: Memory hotunplug
......................................................................

virt: Memory hotunplug

Support for unplugging virtual memory modules, this can be used with
memory hotplug to dynamically set the VM memory size to values that
are not below the initial baseline size given to the VM when it
first started.

Change-Id: I09c878711b9015129f525970f6cc1f11f89998b7
Signed-off-by: Vitor de Lima <vdelima at redhat.com>
---
M client/vdsClient.py
M debian/vdsm.dirs
M lib/vdsm/define.py
M vdsm.spec.in
M vdsm/API.py
M vdsm/hooks.py
M vdsm/rpc/BindingXMLRPC.py
M vdsm/rpc/Bridge.py
M vdsm/rpc/vdsmapi-schema.json
M vdsm/vdsmd.8.in
M vdsm/virt/vm.py
M vdsm_hooks/Makefile.am
12 files changed, 123 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/91/41291/1

diff --git a/client/vdsClient.py b/client/vdsClient.py
index 687f33f..52d0cc0 100755
--- a/client/vdsClient.py
+++ b/client/vdsClient.py
@@ -332,6 +332,13 @@
         params = {'vmId': args[0], 'memory': memory}
         return self.ExecAndExit(self.s.hotplugMemory(params))
 
+    def hotunplugMemory(self, args):
+        memory = self._parseDriveSpec(args[1])
+        memory['type'] = 'memory'
+        memory['device'] = 'memory'
+        params = {'vmId': args[0], 'memory': memory}
+        return self.ExecAndExit(self.s.hotunplugMemory(params))
+
     def setNumberOfCpus(self, args):
         return self.ExecAndExit(self.s.setNumberOfCpus(args[0], args[1]))
 
diff --git a/debian/vdsm.dirs b/debian/vdsm.dirs
index ee2bccd..226b7ad 100644
--- a/debian/vdsm.dirs
+++ b/debian/vdsm.dirs
@@ -27,6 +27,7 @@
 usr/libexec/vdsm/hooks/after_nic_hotunplug_fail
 usr/libexec/vdsm/hooks/after_set_num_of_cpus
 usr/libexec/vdsm/hooks/after_memory_hotplug
+usr/libexec/vdsm/hooks/after_memory_hotunplug
 usr/libexec/vdsm/hooks/after_update_device
 usr/libexec/vdsm/hooks/after_update_device_fail
 usr/libexec/vdsm/hooks/after_vdsm_stop
@@ -54,6 +55,7 @@
 usr/libexec/vdsm/hooks/before_nic_hotunplug
 usr/libexec/vdsm/hooks/before_set_num_of_cpus
 usr/libexec/vdsm/hooks/before_memory_hotplug
+usr/libexec/vdsm/hooks/before_memory_hotunplug
 usr/libexec/vdsm/hooks/before_update_device
 usr/libexec/vdsm/hooks/before_vdsm_start
 usr/libexec/vdsm/hooks/before_vm_cont
diff --git a/lib/vdsm/define.py b/lib/vdsm/define.py
index a1b32d2..907aeb2 100644
--- a/lib/vdsm/define.py
+++ b/lib/vdsm/define.py
@@ -153,6 +153,9 @@
     'hotplugMem': {'status': {
         'code': 66,
         'message': 'Failed to hotplug memory'}},
+    'hotunplugMem': {'status': {
+        'code': 67,
+        'message': 'Failed to hotunplug memory'}},
     'recovery': {'status': {
         'code': 99,
         'message': 'Recovering from crash or Initializing'}},
diff --git a/vdsm.spec.in b/vdsm.spec.in
index ff5d78a..aee040f 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -1261,6 +1261,8 @@
 %dir %{_libexecdir}/%{vdsm_name}/hooks/after_set_num_of_cpus
 %dir %{_libexecdir}/%{vdsm_name}/hooks/before_memory_hotplug
 %dir %{_libexecdir}/%{vdsm_name}/hooks/after_memory_hotplug
+%dir %{_libexecdir}/%{vdsm_name}/hooks/before_memory_hotunplug
+%dir %{_libexecdir}/%{vdsm_name}/hooks/after_memory_hotunplug
 %dir %{_libexecdir}/%{vdsm_name}/hooks/before_get_vm_stats
 %dir %{_libexecdir}/%{vdsm_name}/hooks/after_get_vm_stats
 %dir %{_libexecdir}/%{vdsm_name}/hooks/before_get_all_vm_stats
diff --git a/vdsm/API.py b/vdsm/API.py
index ef1a504..e19bba6 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -488,6 +488,22 @@
 
         return curVm.hotplugMemory(params)
 
+    def hotunplugMemory(self, params):
+        try:
+            utils.validateMinimalKeySet(params, ('vmId', 'memory'))
+        except ValueError:
+            self.log.error('Missing one of required parameters: vmId, memory')
+            return {'status': {'code': errCode['MissParam']['status']['code'],
+                               'message': 'Missing one of required '
+                                          'parameters: vmId, memory'}}
+        try:
+            curVm = self._cif.vmContainer[self._UUID]
+        except KeyError:
+            self.log.warning("vm %s doesn't exist", self._UUID)
+            return errCode['noVM']
+
+        return curVm.hotunplugMemory(params)
+
     def setNumberOfCpus(self, numberOfCpus):
 
         if self._UUID is None or numberOfCpus is None:
diff --git a/vdsm/hooks.py b/vdsm/hooks.py
index c7d6358..12ab847 100644
--- a/vdsm/hooks.py
+++ b/vdsm/hooks.py
@@ -332,6 +332,15 @@
     return _runHooksDir(domxml, 'after_memory_hotplug', vmconf=vmconf,
                         params=params, raiseError=False)
 
+def before_memory_hotunplug(domxml, vmconf={}, params={}):
+    return _runHooksDir(domxml, 'before_memory_hotunplug', vmconf=vmconf,
+                        params=params)
+
+
+def after_memory_hotunplug(domxml, vmconf={}, params={}):
+    return _runHooksDir(domxml, 'after_memory_hotunplug', vmconf=vmconf,
+                        params=params, raiseError=False)
+
 
 def before_vdsm_start():
     return _runHooksDir(None, 'before_vdsm_start', raiseError=False)
diff --git a/vdsm/rpc/BindingXMLRPC.py b/vdsm/rpc/BindingXMLRPC.py
index 5fa511d..c5a6b0c 100644
--- a/vdsm/rpc/BindingXMLRPC.py
+++ b/vdsm/rpc/BindingXMLRPC.py
@@ -438,6 +438,10 @@
         vm = API.VM(params['vmId'])
         return vm.hotplugMemory(params)
 
+    def vmHotunplugMemory(self, params):
+        vm = API.VM(params['vmId'])
+        return vm.hotunplugMemory(params)
+
     def vmSetNumberOfCpus(self, vmId, numberOfCpus):
         vm = API.VM(vmId)
         return vm.setNumberOfCpus(numberOfCpus)
@@ -1036,6 +1040,7 @@
                 (self.vmUpdateDevice, 'vmUpdateDevice'),
                 (self.vmSetNumberOfCpus, 'setNumberOfCpus'),
                 (self.vmHotplugMemory, 'hotplugMemory'),
+                (self.vmHotunplugMemory, 'hotunplugMemory'),
                 (self.merge, 'merge'),
                 (self.vmUpdateVmPolicy, 'updateVmPolicy'),
                 (self.vmSetIoTune, 'setIoTune'),
diff --git a/vdsm/rpc/Bridge.py b/vdsm/rpc/Bridge.py
index d063e67..63869b1 100644
--- a/vdsm/rpc/Bridge.py
+++ b/vdsm/rpc/Bridge.py
@@ -474,6 +474,7 @@
     'VM_setCpuTunePeriod': {'ret': 'taskStatus'},
     'VM_setCpuTuneQuota': {'ret': 'taskStatus'},
     'VM_hotplugMemory':  {'ret': 'vmList'},
+    'VM_hotunplugMemory':  {'ret': 'vmList'},
     'VM_setNumberOfCpus': {'ret': 'vmList'},
     'VM_setIoTune': {'ret': 'taskStatus'},
     'VM_updateDevice': {'ret': 'vmList'},
diff --git a/vdsm/rpc/vdsmapi-schema.json b/vdsm/rpc/vdsmapi-schema.json
index 47e1c1f..135bd0a 100644
--- a/vdsm/rpc/vdsmapi-schema.json
+++ b/vdsm/rpc/vdsmapi-schema.json
@@ -8219,6 +8219,24 @@
  'returns': 'VmDefinition'}
 
 ##
+# @VM.hotunplugMemory:
+#
+# Remove a memory device from a running VM.
+#
+# @vmID:    The UUID of the VM
+#
+# @params:  The VM UUID and memory device information
+#
+# Returns:
+# The VM definition, as updated
+#
+# Since: 4.17.0
+##
+{'command': {'class': 'VM', 'name': 'hotunplugMemory'},
+ 'data': {'vmID': 'UUID', 'params': 'HotplugMemoryParams'},
+ 'returns': 'VmDefinition'}
+
+##
 # @VM.setNumberOfCpus:
 #
 # Set the number CPUs for a VM
diff --git a/vdsm/vdsmd.8.in b/vdsm/vdsmd.8.in
index aab9aca..af70f5a 100644
--- a/vdsm/vdsmd.8.in
+++ b/vdsm/vdsmd.8.in
@@ -64,7 +64,8 @@
     before_get_caps, after_get_caps,
     before_get_stats, after_get_stats,
     after_hostdev_list_by_caps,
-    before_memory_hotplug, after_memory_hotplug.
+    before_memory_hotplug, after_memory_hotplug
+    before_memory_hotunplug, after_memory_hotunplug.
 
 Each hook executes the scripts under
 .FN /usr/libexec/vdsm/hooks/<hook-name>/
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 03028d9..b57040c 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -2182,6 +2182,62 @@
 
         return {'status': doneCode, 'vmList': self.status()}
 
+    def hotunplugMemory(self, params):
+
+        if self.isMigrating():
+            return errCode['migInProgress']
+
+        memParams = params['memory']
+
+        # Find memory object in vm's memory slots
+        mem = None
+        for dev in self._devices[hwclass.MEMORY][:]:
+            if dev.size == (memParams['size'] * 1024):
+                mem = dev
+                break
+
+        if mem:
+            deviceXml = mem.getXML().toprettyxml(encoding='utf-8')
+            hooks.before_memory_hotunplug(deviceXml)
+            self.log.debug("Hotunplug memory xml: %s", deviceXml)
+        else:
+            self.log.error("Hotunplug memory failed - memory not found: %s",
+                           memParams)
+            return response.error('hotunplugMem', "memory not found")
+
+        # Remove found memory device from vm's memory list
+        if mem:
+            self._devices[hwclass.MEMORY].remove(mem)
+        # Find and remove memory device from vm's conf
+        memDev = None
+        for dev in self.conf['devices'][:]:
+            if (dev['type'] == hwclass.MEMORY and
+                        dev['size'] == memParams['size']):
+                with self._confLock:
+                    self.conf['devices'].remove(dev)
+                memDev = dev
+                break
+
+        self.saveState()
+
+        try:
+            self._dom.detachDevice(deviceXml)
+        except libvirt.libvirtError as e:
+            self.log.exception("Hotunplug failed")
+            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
+                return errCode['noVM']
+            # Restore memory device in vm's conf and _devices
+            if memDev:
+                with self._confLock:
+                    self.conf['devices'].append(memDev)
+            if mem:
+                self._devices[hwclass.Memory].append(mem)
+            self.saveState()
+            return response.error('hotunplugMem', e.message)
+
+        hooks.after_memory_hotunplug(deviceXml)
+        return {'status': doneCode, 'vmList': self.status()}
+
     def setNumberOfCpus(self, numberOfCpus):
 
         if self.isMigrating():
diff --git a/vdsm_hooks/Makefile.am b/vdsm_hooks/Makefile.am
index 0da6054..cf6e5b5 100644
--- a/vdsm_hooks/Makefile.am
+++ b/vdsm_hooks/Makefile.am
@@ -129,6 +129,8 @@
 	after_hostdev_list_by_caps \
 	before_memory_hotplug \
 	after_memory_hotplug \
+	before_memory_hotunplug \
+	after_memory_hotunplug \
 	$(NULL)
 
 all-local: \


-- 
To view, visit https://gerrit.ovirt.org/41291
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I09c878711b9015129f525970f6cc1f11f89998b7
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Vitor de Lima <vdelima at redhat.com>


More information about the vdsm-patches mailing list