Change in vdsm[master]: net: move qos reporting to netinfo

ibarkan at redhat.com ibarkan at redhat.com
Thu Dec 3 08:32:21 UTC 2015


Ido Barkan has uploaded a new change for review.

Change subject: net: move qos reporting to netinfo
......................................................................

net: move qos reporting to netinfo

Up until now, qos reporting was part of caps.py, which lies in an
upper layer then netinfo, just because the tc code could not be used
from within netinfo. Now it is possible to bury this reporting code
inside netinfo new package, where it belongs.

Change-Id: Ie3526c4ae609f29561904bddacc1e9f9194435e9
Signed-off-by: Ido Barkan <ibarkan at redhat.com>
---
M debian/vdsm-python.install
M lib/vdsm/netinfo/Makefile.am
M lib/vdsm/netinfo/__init__.py
A lib/vdsm/netinfo/qos.py
M lib/vdsm/network/configurators/qos.py
M lib/vdsm/tc/__init__.py
M tests/functional/networkTests.py
M tests/qosTests.py
M tests/tcTests.py
M vdsm.spec.in
M vdsm/caps.py
11 files changed, 88 insertions(+), 62 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/20/49620/1

diff --git a/debian/vdsm-python.install b/debian/vdsm-python.install
index 833d611..cdef597 100644
--- a/debian/vdsm-python.install
+++ b/debian/vdsm-python.install
@@ -24,6 +24,7 @@
 ./usr/lib/python2.7/dist-packages/vdsm/netinfo/misc.py
 ./usr/lib/python2.7/dist-packages/vdsm/netinfo/mtus.py
 ./usr/lib/python2.7/dist-packages/vdsm/netinfo/nics.py
+./usr/lib/python2.7/dist-packages/vdsm/netinfo/qos.py
 ./usr/lib/python2.7/dist-packages/vdsm/netinfo/routes.py
 ./usr/lib/python2.7/dist-packages/vdsm/netinfo/vlans.py
 ./usr/lib/python2.7/dist-packages/vdsm/netlink/__init__.py
diff --git a/lib/vdsm/netinfo/Makefile.am b/lib/vdsm/netinfo/Makefile.am
index f8ce871..bac2915 100644
--- a/lib/vdsm/netinfo/Makefile.am
+++ b/lib/vdsm/netinfo/Makefile.am
@@ -30,6 +30,7 @@
 	misc.py \
 	mtus.py \
 	nics.py \
+	qos.py \
 	routes.py \
 	vlans.py \
 	$(NULL)
diff --git a/lib/vdsm/netinfo/__init__.py b/lib/vdsm/netinfo/__init__.py
index a904d0c..f3d2421 100644
--- a/lib/vdsm/netinfo/__init__.py
+++ b/lib/vdsm/netinfo/__init__.py
@@ -40,6 +40,7 @@
 from .mtus import getMtu
 from .nics import nicinfo
 from .routes import get_routes, get_gateway
+from .qos import report_network_qos
 from .vlans import vlaninfo, vlan_id, vlan_device
 
 
@@ -91,6 +92,8 @@
         updates = propose_updates_to_reported_dhcp(network_info, networking)
         update_reported_dhcp(updates, networking)
 
+    report_network_qos(networking)
+
     return networking
 
 
diff --git a/lib/vdsm/netinfo/qos.py b/lib/vdsm/netinfo/qos.py
new file mode 100644
index 0000000..235d575
--- /dev/null
+++ b/lib/vdsm/netinfo/qos.py
@@ -0,0 +1,59 @@
+#
+# Copyright 2015 Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+
+from collections import defaultdict
+
+from vdsm import tc
+from vdsm.network.configurators import qos
+
+
+def report_network_qos(netinfo):
+    """Augment netinfo information with QoS data for the engine"""
+    qdiscs = defaultdict(list)
+    for qdisc in tc.qdiscs(dev=None):  # None -> all dev qdiscs
+        qdiscs[qdisc['dev']].append(qdisc)
+    for net, attrs in netinfo['networks'].iteritems():
+        iface = attrs['iface']
+        if iface in netinfo['bridges']:
+            host_ports = [port for port in attrs['ports'] if
+                          not port.startswith('vnet')]
+            if not host_ports:  # Port-less bridge
+                continue
+            iface, = host_ports
+        if iface in netinfo['vlans']:
+            vlan_id = netinfo['vlans'][iface]['vlanid']
+            iface = netinfo['vlans'][iface]['iface']
+            iface_qdiscs = qdiscs.get(iface)
+            if iface_qdiscs is None:
+                continue
+            class_id = (qos.get_root_qdisc(iface_qdiscs)['handle'] + '%x' %
+                        vlan_id)
+        else:
+            iface_qdiscs = qdiscs.get(iface)
+            if iface_qdiscs is None:
+                continue
+            class_id = (qos.get_root_qdisc(iface_qdiscs)['handle'] +
+                        qos.DEFAULT_CLASSID)
+
+        # Now that iface is either a bond or a nic, let's get the QoS info
+        classes = [cls for cls in tc.classes(iface, classid=class_id) if
+                   cls['kind'] == 'hfsc']
+        if classes:
+            cls, = classes
+            attrs['hostQos'] = {'out': cls['hfsc']}
diff --git a/lib/vdsm/network/configurators/qos.py b/lib/vdsm/network/configurators/qos.py
index f3dd456..4a066dd 100644
--- a/lib/vdsm/network/configurators/qos.py
+++ b/lib/vdsm/network/configurators/qos.py
@@ -25,7 +25,7 @@
 from vdsm import tc
 
 _NON_VLANNED_ID = 5000
-_DEFAULT_CLASSID = '%x' % _NON_VLANNED_ID
+DEFAULT_CLASSID = '%x' % _NON_VLANNED_ID
 _ROOT_QDISC_HANDLE = '%x:' % 5001  # Leave 0 free for leaf qdisc of vlan tag 0
 _FAIR_QDISC_KIND = 'fq_codel' if (StrictVersion(os.uname()[2].split('-')[0]) >
                                   StrictVersion('3.5.0')) else 'sfq'
@@ -36,7 +36,7 @@
     """Adds the qosOutbound configuration to the backing device (be it bond
     or nic). Adds a class and filter for default traffic if necessary. vlan_tag
     can be None"""
-    root_qdisc = _root_qdisc(tc._qdiscs(device))
+    root_qdisc = get_root_qdisc(tc.qdiscs(device))
     class_id = '%x' % (_NON_VLANNED_ID if vlan_tag is None else vlan_tag)
     if not root_qdisc or root_qdisc['kind'] != _SHAPING_QDISC_KIND:
         _fresh_qdisc_conf_out(device, vlan_tag, class_id, qosOutbound)
@@ -59,10 +59,10 @@
         if tce.errCode not in MISSING_OBJ_ERR_CODES:  # No filter exists
             raise
 
-    device_qdiscs = list(tc._qdiscs(device))
+    device_qdiscs = list(tc.qdiscs(device))
     if not device_qdiscs:
         return
-    root_qdisc_handle = _root_qdisc(device_qdiscs)['handle']
+    root_qdisc_handle = get_root_qdisc(device_qdiscs)['handle']
     try:
         tc.cls.delete(device, classid=root_qdisc_handle + class_id)
     except tc.TrafficControlException as tce:
@@ -82,12 +82,12 @@
     """Returns true iff there's traffic classes in the device, ignoring the
     root class and a default unused class"""
     if root_qdisc_handle is None:
-        root_qdisc_handle = _root_qdisc(tc._qdiscs(device))['handle']
+        root_qdisc_handle = get_root_qdisc(tc.qdiscs(device))['handle']
     classes = [cls for cls in tc.classes(device, parent=root_qdisc_handle) if
                not cls.get('root')]
     return (classes and
             not(len(classes) == 1 and not netinfo.ifaceUsed(device) and
-                classes[0]['handle'] == root_qdisc_handle + _DEFAULT_CLASSID))
+                classes[0]['handle'] == root_qdisc_handle + DEFAULT_CLASSID))
 
 
 def _fresh_qdisc_conf_out(dev, vlan_tag, class_id, qos):
@@ -111,18 +111,18 @@
 
     # Add traffic classes
     _add_hfsc_cls(dev, _ROOT_QDISC_HANDLE, class_id, **qos)
-    if class_id != _DEFAULT_CLASSID:  # We need to add a default class
-        _add_hfsc_cls(dev, _ROOT_QDISC_HANDLE, _DEFAULT_CLASSID, ls=qos['ls'])
+    if class_id != DEFAULT_CLASSID:  # We need to add a default class
+        _add_hfsc_cls(dev, _ROOT_QDISC_HANDLE, DEFAULT_CLASSID, ls=qos['ls'])
 
     # Add filters to move the traffic into the classes we just created
     _add_non_vlanned_filter(dev, _ROOT_QDISC_HANDLE)
-    if class_id != _DEFAULT_CLASSID:
+    if class_id != DEFAULT_CLASSID:
         _add_vlan_filter(dev, vlan_tag, _ROOT_QDISC_HANDLE, class_id)
 
     # Add inside intra-class fairness qdisc (fq_codel/sfq)
     _add_fair_qdisc(dev, _ROOT_QDISC_HANDLE, class_id)
-    if class_id != _DEFAULT_CLASSID:
-        _add_fair_qdisc(dev, _ROOT_QDISC_HANDLE, _DEFAULT_CLASSID)
+    if class_id != DEFAULT_CLASSID:
+        _add_fair_qdisc(dev, _ROOT_QDISC_HANDLE, DEFAULT_CLASSID)
 
 
 def _qdisc_conf_out(dev, root_qdisc_handle, vlan_tag, class_id, qos):
@@ -152,7 +152,7 @@
             raise
 
     _add_hfsc_cls(dev, root_qdisc_handle, class_id, **qos)
-    if class_id == _DEFAULT_CLASSID:
+    if class_id == DEFAULT_CLASSID:
         _add_non_vlanned_filter(dev, root_qdisc_handle)
     else:
         _add_vlan_filter(dev, vlan_tag, root_qdisc_handle, class_id)
@@ -184,7 +184,7 @@
                classid=root_qdisc_handle + class_id, **qos_opts)
 
 
-def _root_qdisc(qdiscs):
+def get_root_qdisc(qdiscs):
     for qdisc in qdiscs:
         if 'root' in qdisc:
             return qdisc
diff --git a/lib/vdsm/tc/__init__.py b/lib/vdsm/tc/__init__.py
index a623d1e..f89b3c6 100644
--- a/lib/vdsm/tc/__init__.py
+++ b/lib/vdsm/tc/__init__.py
@@ -114,7 +114,7 @@
 
 def _qdiscs_of_device(dev):
     "Return an iterator of qdisc_ids associated with dev"
-    for qdisc_data in _qdiscs(dev):
+    for qdisc_data in qdiscs(dev):
         yield qdisc_data['handle']
 
 
@@ -160,5 +160,5 @@
 
 
 _filters = partial(_iterate, tc_filter)  # kwargs: parent and pref
-_qdiscs = partial(_iterate, qdisc)  # kwargs: dev
+qdiscs = partial(_iterate, qdisc)  # kwargs: dev
 classes = partial(_iterate, cls)  # kwargs: parent and classid
diff --git a/tests/functional/networkTests.py b/tests/functional/networkTests.py
index ff8d455..a37f248 100644
--- a/tests/functional/networkTests.py
+++ b/tests/functional/networkTests.py
@@ -2445,7 +2445,7 @@
                              'Failed to cleanup tc classes')
             # Real devices always get a qdisc, dummies don't, so 0 after
             # deletion.
-            self.assertEqual(0, len(list(tc._qdiscs(nic))),
+            self.assertEqual(0, len(list(tc.qdiscs(nic))),
                              'Failed to cleanup tc hfsc and ingress qdiscs')
             self.assertEqual(status, SUCCESS, msg)
 
diff --git a/tests/qosTests.py b/tests/qosTests.py
index fca5845..c685d9c 100644
--- a/tests/qosTests.py
+++ b/tests/qosTests.py
@@ -47,4 +47,4 @@
                 'sfq': {'limit': 127, 'quantum': 1514}},
                {'kind': 'sfq', 'handle': '20:', 'parent': '1:20',
                 'sfq': {'limit': 127, 'quantum': 1514}})
-        self.assertEqual(qos._root_qdisc(inp), root)
+        self.assertEqual(qos.get_root_qdisc(inp), root)
diff --git a/tests/tcTests.py b/tests/tcTests.py
index 0bc6176..c9cb626 100644
--- a/tests/tcTests.py
+++ b/tests/tcTests.py
@@ -213,7 +213,7 @@
                           'target': 5000.0, 'interval': 150000.0,
                           'ecn': True}},
         )
-        for parsed, correct in izip_longest(tc._qdiscs(None, out=data),
+        for parsed, correct in izip_longest(tc.qdiscs(None, out=data),
                                             qdiscs):
             self.assertEqual(parsed, correct)
 
@@ -530,7 +530,7 @@
         return TcClasses(all_classes, default_class, root_class)
 
     def _analyse_qdiscs(self):
-        all_qdiscs = list(tc._qdiscs(self.device_name))
+        all_qdiscs = list(tc.qdiscs(self.device_name))
         ingress_qdisc = self._ingress_qdisc(all_qdiscs)
         root_qdisc = self._root_qdisc(all_qdiscs)
         leaf_qdiscs = self._leaf_qdiscs(all_qdiscs)
@@ -576,7 +576,7 @@
 
     def _assertions_on_default_class(self, default_class):
         self._assert_parent_handle([default_class], qos._ROOT_QDISC_HANDLE)
-        self.assertEqual(default_class['leaf'], qos._DEFAULT_CLASSID + ':')
+        self.assertEqual(default_class['leaf'], qos.DEFAULT_CLASSID + ':')
         self.assertEqual(default_class[qos._SHAPING_QDISC_KIND]['ls'],
                          HOST_QOS_OUTBOUND['ls'])
 
@@ -597,7 +597,7 @@
         return _find_entity(lambda c: c.get('root'), classes)
 
     def _default_class(self, classes):
-        default_cls_handle = qos._ROOT_QDISC_HANDLE + qos._DEFAULT_CLASSID
+        default_cls_handle = qos._ROOT_QDISC_HANDLE + qos.DEFAULT_CLASSID
         return _find_entity(lambda c: c['handle'] == default_cls_handle,
                             classes)
 
@@ -631,7 +631,7 @@
         return _find_entity(lambda c: c['handle'] == handle, classes)
 
     def _non_vlan_qdisc(self, qdiscs):
-        handle = qos._DEFAULT_CLASSID + ':'
+        handle = qos.DEFAULT_CLASSID + ':'
         return _find_entity(lambda q: q['handle'] == handle, qdiscs)
 
 
diff --git a/vdsm.spec.in b/vdsm.spec.in
index 2f71ea2..1b4438a 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -1087,6 +1087,7 @@
 %{python_sitelib}/%{vdsm_name}/netinfo/misc.py*
 %{python_sitelib}/%{vdsm_name}/netinfo/mtus.py*
 %{python_sitelib}/%{vdsm_name}/netinfo/nics.py*
+%{python_sitelib}/%{vdsm_name}/netinfo/qos.py*
 %{python_sitelib}/%{vdsm_name}/netinfo/routes.py*
 %{python_sitelib}/%{vdsm_name}/netinfo/vlans.py*
 %{python_sitelib}/%{vdsm_name}/netlink/__init__.py*
diff --git a/vdsm/caps.py b/vdsm/caps.py
index 186a3d4..5de7ff9 100644
--- a/vdsm/caps.py
+++ b/vdsm/caps.py
@@ -23,7 +23,6 @@
 import itertools
 import os
 import platform
-from collections import defaultdict
 import logging
 import time
 import linecache
@@ -35,8 +34,7 @@
 import libvirt
 
 from vdsm.config import config
-from vdsm import libvirtconnection, tc
-from vdsm.network.configurators import qos
+from vdsm import libvirtconnection
 import dsaversion
 from vdsm import netinfo
 import hooks
@@ -87,42 +85,6 @@
 
 RNG_SOURCES = {'random': '/dev/random',
                'hwrng': '/dev/hwrng'}
-
-
-def _report_network_qos(caps):
-    """Augment netinfo information with QoS data for the engine"""
-    qdiscs = defaultdict(list)
-    for qdisc in tc._qdiscs(dev=None):  # None -> all dev qdiscs
-        qdiscs[qdisc['dev']].append(qdisc)
-    for net, attrs in caps['networks'].iteritems():
-        iface = attrs['iface']
-        if iface in caps['bridges']:
-            host_ports = [port for port in attrs['ports'] if
-                          not port.startswith('vnet')]
-            if not host_ports:  # Port-less bridge
-                continue
-            iface, = host_ports
-        if iface in caps['vlans']:
-            vlan_id = caps['vlans'][iface]['vlanid']
-            iface = caps['vlans'][iface]['iface']
-            iface_qdiscs = qdiscs.get(iface)
-            if iface_qdiscs is None:
-                continue
-            class_id = (qos._root_qdisc(iface_qdiscs)['handle'] + '%x' %
-                        vlan_id)
-        else:
-            iface_qdiscs = qdiscs.get(iface)
-            if iface_qdiscs is None:
-                continue
-            class_id = (qos._root_qdisc(iface_qdiscs)['handle'] +
-                        qos._DEFAULT_CLASSID)
-
-        # Now that iface is either a bond or a nic, let's get the QoS info
-        classes = [cls for cls in tc.classes(iface, classid=class_id) if
-                   cls['kind'] == 'hfsc']
-        if classes:
-            cls, = classes
-            attrs['hostQos'] = {'out': cls['hfsc']}
 
 
 class Architecture:
@@ -668,7 +630,6 @@
 
     caps.update(_getVersionInfo())
     caps.update(netinfo.get())
-    _report_network_qos(caps)
 
     try:
         caps['hooks'] = hooks.installed()


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie3526c4ae609f29561904bddacc1e9f9194435e9
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Ido Barkan <ibarkan at redhat.com>


More information about the vdsm-patches mailing list