Jiří Moskovčák has uploaded a new change for review. Change subject: added support for controlling iotune params ......................................................................
added support for controlling iotune params Change-Id: Ic44e0780bbcc808fe057c378ac83af4d7729a2fb Signed-off-by: Jiri Moskovcak <[email protected]> --- A mom/Collectors/GuestIOTune.py A mom/Controllers/IoTune.py M mom/HypervisorInterfaces/libvirtInterface.py M mom/HypervisorInterfaces/vdsmInterface.py 4 files changed, 195 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/mom refs/changes/51/31251/1 diff --git a/mom/Collectors/GuestIOTune.py b/mom/Collectors/GuestIOTune.py new file mode 100644 index 0000000..ba87b34 --- /dev/null +++ b/mom/Collectors/GuestIOTune.py @@ -0,0 +1,55 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +from mom.Collectors.Collector import Collector +import logging +import simplejson + + +class GuestIOTune(Collector): + """ + This Collector uses hypervisor interface to collect devices io info + + Libvirt's io data (http://libvirt.org/formatdomain.html#elementsDisks) + + at the moment mom doesn't support iteration, so we can't do much with + list of devices with their iotune params + """ + + def getFields(self=None): + return {'iotunedata'} + + def __init__(self, properties): + self.hypervisor_iface = properties['hypervisor_iface'] + self.uuid = properties['uuid'] + self.logger = logging.getLogger(__name__) + self.iotune_info_available = True + + def stats_error(self, msg): + """ + Only print stats interface errors one time when we first discover a + problem. Otherwise the log will be overrun with noise. + """ + if self.iotune_info_available: + self.logger.debug(msg) + self.iotune_info_available = False + + def collect(self): + stat = self.hypervisor_iface.getVmIOTuneInfo(self.uuid) + + if stat is None: + self.stats_error('getVmIOTuneInfo() is not ready') + else: + self.iotune_info_available = False + + return simplejson.dumps(stat) diff --git a/mom/Controllers/IoTune.py b/mom/Controllers/IoTune.py new file mode 100644 index 0000000..b5e30dd --- /dev/null +++ b/mom/Controllers/IoTune.py @@ -0,0 +1,58 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import logging +import simplejson + + +class IoTune: + """ + Controller that uses the hypervisor interface to manipulate + the io tuning parameters. + The current parameters that can be set are: + total_bytes_sec: Total throughput in bytes per second + read_iops_sec: Total read operations per second + write_iops_sec: Total write operations per second + For more: http://libvirt.org/formatdomain.html#elementsDevices + """ + def __init__(self, properties): + self.hypervisor_iface = properties['hypervisor_iface'] + self.logger = logging.getLogger('mom.Controllers.Iotune') + # need to save and check the old value here, + # because the policy parser can't process it + self._prev_iotune = {} + + def process_guest(self, guest): + if guest.iotunedata: + try: + iotunedata = simplejson.loads(guest.iotunedata) + except simplejson.scanner.JSONDecodeError as e: + self.logger.error("Can't decode iotune params from json: '{0}'" + .format(e)) + return + + # nothing has changed, no need to set it again + if self._prev_iotune == iotunedata: + return + + if iotunedata is not None: + uuid = guest.Prop('uuid') + name = guest.Prop('name') + self.logger.info("Updating IoTune params for guest: {0}" + .format(name)) + self.hypervisor_iface.setVmIoTune(uuid, iotunedata) + + def process(self, host, guests): + for guest in guests: + self.process_guest(guest) + diff --git a/mom/HypervisorInterfaces/libvirtInterface.py b/mom/HypervisorInterfaces/libvirtInterface.py index a44fdd1..0405a7b 100644 --- a/mom/HypervisorInterfaces/libvirtInterface.py +++ b/mom/HypervisorInterfaces/libvirtInterface.py @@ -287,6 +287,69 @@ return ret + def _getDriveIdentification(self, dom): + sources = dom.getElementsByTagName('source') + if sources: + devPath = (sources[0].getAttribute('file') or + sources[0].getAttribute('dev') or + sources[0].getAttribute('name')) + else: + devPath = '' + target = dom.getElementsByTagName('target') + name = target[0].getAttribute('dev') if target else None + alias = dom.getElementsByTagName('alias')[0].getAttribute('name') + return alias, devPath, name + + def getVmIoTuneInfo(self, uuid): + tunables = [] + domain = self._getDomainFromUUID(uuid) + + # Get the user selection for vcpuLimit from the metadata + iotuneMetadata = None + try: + iotuneMetadata = domain.metadata( + libvirt.VIR_DOMAIN_METADATA_ELEMENT, _METADATA_VM_TUNE_URI, 0) + except libvirt.libvirtError as e: + if e.get_error_code() != libvirt.VIR_ERR_NO_DOMAIN_METADATA: + self.logger.error("Failed to retrieve iotune QoS metadata") + + # vdsm setIoTune expects list of dict describing the device and it's + # iotune params + # [{"name": <device>, + # "path": <path>, + # "alias": <alias>, + # "ioTune": { + # "total_bytes_sec":10000000, + # "read_iops_sec": 400000, + # "write_iops_sec": 100000, + # } + # }] + if iotuneMetadata: + iotune_xml = _domParseStr(iotuneMetadata) + diskNodes = \ + iotune_xml.getElementsByTagName("devices") + + for disk in diskNodes: + iotune_node = disk.getElementsByTagName("iotune")[0] + if iotune_node: + alias, devPath, name = self._getDriveIdentification(disk) + tunables.append({ + "name": name, + "alias": alias, + "path": devPath, + "ioTune": + { + "total_bytes_sec": + iotune_node.getElementsByTagName("total_bytes_sec"), + "read_iops_sec": + iotune_node.getElementsByTagName("read_iops_sec"), + "write_iops_sec": + iotune_node.getElementsByTagName("write_iops_sec") + } + }) + + return tunables + def setVmBalloonTarget(self, uuid, target): dom = self._getDomainFromUUID(uuid) if dom is not None: @@ -302,6 +365,16 @@ self.logger.error("libvirtInterface: Exception while " \ "setSchedulerParameters: %s", e.message); + def setVmIoTune(self, uuid, devices): + dom = self._getDomainFromUUID(uuid) + + for device in devices: + try: + dom.setBlockIoTune(device['devPath'], device['ioTune']) + except libvirt.libvirtError, e: + self.logger.error("libvirtInterface: Exception while " + "setInterfaceParameters: %s", e.message) + def ksmTune(self, tuningParams): def write_value(fname, value): try: diff --git a/mom/HypervisorInterfaces/vdsmInterface.py b/mom/HypervisorInterfaces/vdsmInterface.py index 1193785..d16fd98 100644 --- a/mom/HypervisorInterfaces/vdsmInterface.py +++ b/mom/HypervisorInterfaces/vdsmInterface.py @@ -211,6 +211,15 @@ except vdsmException, e: e.handle_exception() + def getVmIoTuneInfo(self, uuid): + try: + ret = {} + vm = API.VM(uuid) + response = vm.getStats() + self._check_status(response) + except vdsmException as e: + e.handle_exception() + def ksmTune(self, tuningParams): # When MOM is lauched by vdsm, it's running without root privileges. # So we need resort to supervdsm to set the KSM parameters. -- To view, visit http://gerrit.ovirt.org/31251 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic44e0780bbcc808fe057c378ac83af4d7729a2fb Gerrit-PatchSet: 1 Gerrit-Project: mom Gerrit-Branch: master Gerrit-Owner: Jiří Moskovčák <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
