Hello Andrej Krejcir, I'd like you to do a code review. Please visit
https://gerrit.ovirt.org/55820 to review the following change. Change subject: Apply storage QoS on running VM ...................................................................... Apply storage QoS on running VM Modified updateVmPolicy command to accept disk ids. Added a function to get current io tune from libvirt. Change-Id: I3f5fcb8705c974f1d91c90cdb3158d2e8dd314f8 Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1201482 Signed-off-by: Andrej Krejcir <akrej...@redhat.com> --- M tests/vmTests.py M vdsm/API.py M vdsm/rpc/Bridge.py M vdsm/rpc/bindingxmlrpc.py M vdsm/rpc/vdsmapi-schema.json M vdsm/virt/vm.py 6 files changed, 106 insertions(+), 7 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/20/55820/1 diff --git a/tests/vmTests.py b/tests/vmTests.py index a0d7d0b..5471c03 100644 --- a/tests/vmTests.py +++ b/tests/vmTests.py @@ -809,7 +809,7 @@ self.assertEqual(expected_xml, self._xml_sanitizer(dom._metadata)) - def testGetIoTune(self): + def testGetIoTunePolicy(self): with fake.VM() as machine: dom = fake.Domain() dom._metadata = """ @@ -842,7 +842,7 @@ u'totalBytes': 9999 }} ] - self.assertEqual(tunables, expected) + self.assertEqual(tunables['ioTunePolicy'], expected) def testSetIoTune(self): diff --git a/vdsm/API.py b/vdsm/API.py index d5f6ced..46c5e66 100644 --- a/vdsm/API.py +++ b/vdsm/API.py @@ -770,6 +770,12 @@ return errCode['noVM'] return v.setCpuTuneQuota(quota) + def getIoTune(self): + v = self._cif.vmContainer.get(self._UUID) + if not v: + return errCode['noVM'] + return v.getIoTune() + def setIoTune(self, tunables): v = self._cif.vmContainer.get(self._UUID) if not v: diff --git a/vdsm/rpc/Bridge.py b/vdsm/rpc/Bridge.py index c2a114c..8815a18 100644 --- a/vdsm/rpc/Bridge.py +++ b/vdsm/rpc/Bridge.py @@ -470,6 +470,7 @@ 'VM_diskSizeExtend': {'ret': 'size'}, 'VM_getDiskAlignment': {'ret': 'alignment'}, 'VM_getInfo': {'call': VM_getInfo_Call, 'ret': VM_getInfo_Ret}, + 'VM_getIoTune': {'ret': 'ioTuneList'}, 'VM_getIoTunePolicy': {'ret': 'ioTunePolicyList'}, 'VM_getStats': {'ret': 'statsList'}, 'VM_hotplugDisk': {'ret': 'vmList'}, diff --git a/vdsm/rpc/bindingxmlrpc.py b/vdsm/rpc/bindingxmlrpc.py index c521cd8..acb3bbd 100644 --- a/vdsm/rpc/bindingxmlrpc.py +++ b/vdsm/rpc/bindingxmlrpc.py @@ -554,6 +554,10 @@ vm = API.VM(vmId) return vm.getIoTunePolicy() + def vmGetIoTune(self, vmId): + vm = API.VM(vmId) + return vm.getIoTune() + def vmSetIoTune(self, vmId, tunables): vm = API.VM(vmId) return vm.setIoTune(tunables) @@ -1108,6 +1112,7 @@ (self.merge, 'merge'), (self.vmUpdateVmPolicy, 'updateVmPolicy'), (self.vmSetIoTune, 'setIoTune'), + (self.vmGetIoTune, 'getIoTune'), (self.vmGetIoTunePolicy, 'getIoTunePolicy'), (self.vmSetCpuTuneQuota, 'vmSetCpuTuneQuota'), (self.vmSetCpuTunePeriod, 'vmSetCpuTunePeriod'), diff --git a/vdsm/rpc/vdsmapi-schema.json b/vdsm/rpc/vdsmapi-schema.json index 8ca7627..cface3b 100644 --- a/vdsm/rpc/vdsmapi-schema.json +++ b/vdsm/rpc/vdsmapi-schema.json @@ -2582,10 +2582,19 @@ # @VmDiskDeviceTuneLimits: # # Extra parameters for VM disk devices. +# Either name, path or all 4 IDs must be present # # @name: #optional The name of the target device # # @path: #optional The path of the target device +# +# @domainID: #optional DomainID +# +# @poolID: #optional PoolId +# +# @imageID: #optional ImageId +# +# @volumeID: #optional VolumeId # # @guaranteed: IO tune parameters - guaranteed values # @@ -2595,6 +2604,8 @@ ## {'type': 'VmDiskDeviceTuneLimits', 'data': {'*name': 'str', '*path': 'str', + '*domainID': 'UUID', '*poolID': 'UUID', + '*imageID': 'UUID', '*volumeID': 'UUID', 'guaranteed': 'VmDiskDeviceIoTuneParams', 'maximum': 'VmDiskDeviceIoTuneParams'}} @@ -8705,6 +8716,23 @@ 'returns': 'TaskStatus'} ## +# @VM.getIoTune: +# +# Sets the ioTune parameters for block devices +# +# @vmID: The UUID of the VM +# +# Returns: +# list of VmDiskDeviceTuneParams objects +# +# Since: 4.18.0 +## +{'command': {'class': 'VM', 'name': 'getIoTune'}, + 'data': {'vmID': 'UUID'}, + 'returns': ['VmDiskDeviceTuneParams']} + + +## # @VM.getIoTunePolicy: # # Gets the ioTune policy settings for block devices @@ -8712,14 +8740,14 @@ # @vmID: The UUID of the VM # # Returns: -# list of VmDiskDeviceTuneParams objects describing +# list of VmDiskDeviceTuneLimits objects describing # the current settings # # Since: 4.15.0 ## {'command': {'class': 'VM', 'name': 'getIoTunePolicy'}, 'data': {'vmID': 'UUID'}, - 'returns': ['VmDiskDeviceTuneParams']} + 'returns': ['VmDiskDeviceTuneLimits']} ## # @VM.setCpuTuneQuota: diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py index 81c166d..4d0a96d 100644 --- a/vdsm/virt/vm.py +++ b/vdsm/virt/vm.py @@ -2465,6 +2465,32 @@ self._vcpuLimit = params.pop('vcpuLimit') if 'ioTune' in params: + ioTuneParams = params["ioTune"] + + for ioTune in ioTuneParams: + if ("path" in ioTune) or ("name" in ioTune): + continue + + self.log.debug("IoTuneParams: %s", str(ioTune)) + + try: + # All 4 IDs are required to identify a device + # If there is a valid reason why not all 4 are required, + # please change the code + + disk = self._findDriveByUUIDs({ + 'domainID': ioTune["domainID"], + 'poolID': ioTune["poolID"], + 'imageID': ioTune["imageID"], + 'volumeID': ioTune["volumeID"]}) + + self.log.debug("Device path: %s", disk.path) + ioTune["name"] = disk.name + ioTune["path"] = disk.path + + except LookupError as e: + return response.error('updateVmPolicyErr', e.message) + # Make sure the top level element exists ioTuneList = qos.getElementsByTagName("ioTune") if not ioTuneList: @@ -2473,7 +2499,7 @@ qos.appendChild(ioTuneElement) metadata_modified = True - if update_io_tune_dom(ioTuneList[0], params["ioTune"]) > 0: + if update_io_tune_dom(ioTuneList[0], ioTuneParams) > 0: metadata_modified = True del params['ioTune'] @@ -2543,12 +2569,45 @@ qos = self._getVmPolicy() ioTuneList = qos.getElementsByTagName("ioTune") if not ioTuneList or not ioTuneList[0].hasChildNodes(): - return [] + return response.success(ioTunePolicy=[]) for device in ioTuneList[0].getElementsByTagName("device"): tunables.append(io_tune_dom_to_values(device)) - return tunables + return response.success(ioTunePolicy=tunables) + + def getIoTune(self): + resultList = [] + + for device in self.getDiskDevices(): + if not isVdsmImage(device): + continue + + try: + res = self._dom.blockIoTune( + device.name, + libvirt.VIR_DOMAIN_AFFECT_LIVE) + + # use only certain fields, otherwise + # Drive._validateIoTuneParams will not pass + ioTune = {k: res[k] for k in ( + 'total_bytes_sec', 'read_bytes_sec', + 'write_bytes_sec', 'total_iops_sec', + 'write_iops_sec', 'read_iops_sec')} + + resultList.append({ + 'name': device.name, + 'path': device.path, + 'ioTune': ioTune}) + + except libvirt.libvirtError as e: + self.log.exception("getVmIoTune failed") + if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN: + return response.error('noVM') + else: + return response.error('updateIoTuneErr', e.message) + + return response.success(ioTune=resultList) def setIoTune(self, tunables): for io_tune_change in tunables: -- To view, visit https://gerrit.ovirt.org/55820 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3f5fcb8705c974f1d91c90cdb3158d2e8dd314f8 Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: ovirt-3.6 Gerrit-Owner: Roman Mohr <rm...@redhat.com> Gerrit-Reviewer: Andrej Krejcir <akrej...@redhat.com> _______________________________________________ vdsm-patches mailing list vdsm-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches