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

Reply via email to