Change in vdsm[master]: Qos feature: Adds bandwidth definition at configuration leve...

gvallare at redhat.com gvallare at redhat.com
Fri Jun 14 14:05:59 UTC 2013


Giuseppe Vallarelli has uploaded a new change for review.

Change subject: Qos feature: Adds bandwidth definition at configuration level.
......................................................................

Qos feature: Adds bandwidth definition at configuration level.

Network definition when configuring libvirt network is enriched with
the optional bandwidth parameters for traffic shaping. Patch includes
a refactoring of the xml generation and some tests.

Change-Id: If0c3b4b9a6fd5eb53579fb2e157b5325caa88d04
Signed-off-by: Giuseppe Vallarelli <gvallare at redhat.com>
---
M tests/netconfTests.py
M vdsm/configNetwork.py
M vdsm/netconf/ifcfg.py
M vdsm_api/vdsmapi-schema.json
4 files changed, 140 insertions(+), 42 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/24/15724/1

diff --git a/tests/netconfTests.py b/tests/netconfTests.py
index 26d8ac2..a8a777a 100644
--- a/tests/netconfTests.py
+++ b/tests/netconfTests.py
@@ -25,6 +25,7 @@
 import shutil
 import subprocess
 import tempfile
+from xml.etree import ElementTree
 
 from vdsm import netinfo
 from netconf import ifcfg
@@ -70,17 +71,27 @@
                 restoredContent = file(fn).read()
                 self.assertEqual(content, restoredContent)
 
+    def assertEqualXml(self, a, b):
+        """
+        Compare two xml artifacts for equality.
+        """
+        contents_a = ElementTree.tostring(ElementTree.fromstring(a))
+        contents_b = ElementTree.tostring(ElementTree.fromstring(b))
+        return contents_a == contents_b
+
+    def setUp(self):
+        self.cw = ifcfg.ConfigWriter()
+
     @MonkeyPatch(subprocess, 'Popen', lambda x: None)
     def testAtomicRestore(self):
-        cw = ifcfg.ConfigWriter()
         self._createFiles()
 
         for fn, _, _ in self._files:
-            cw._atomicBackup(fn)
+            self.cw._atomicBackup(fn)
 
         self._makeFilesDirty()
 
-        cw.restoreAtomicBackup()
+        self.cw.restoreAtomicBackup()
         self._assertFilesRestored()
 
     @MonkeyPatch(os, 'chown', lambda *x: 0)
@@ -105,15 +116,56 @@
                 raise SkipTest("'vdsm' is not in user account database, "
                                "install vdsm package to create the vdsm user")
 
-            cw = ifcfg.ConfigWriter()
             self._createFiles()
 
             for fn, _, _ in self._files:
-                cw._persistentBackup(fn)
+                self.cw._persistentBackup(fn)
 
             self._makeFilesDirty()
 
-            cw = ifcfg.ConfigWriter()
-            cw.restorePersistentBackup()
+            self.cw.restorePersistentBackup()
 
             self._assertFilesRestored()
+
+    def testCreateNetXmlBridged(self):
+        netName = "awesome_net"
+        network = "dummy"
+        expectedDoc = ("""<network>
+                            <name>%s</name>
+                            <forward mode='bridge'/>
+                            <bridge name='%s'/>
+                          </network>""" % (netName, network))
+        actualDoc = self.cw.createNetXml(netName, network, True, None)
+
+        self.assertEqualXml(expectedDoc, actualDoc)
+
+    def testCreateNetXml(self):
+        netName = "awesome_net"
+        iface = "dummy"
+        expectedDoc = ("""<network>
+                            <name>%s</name>
+                            <forward mode='passthrough'/>
+                            <interface dev='%s'/>
+                          </network>""" % (netName, iface))
+        actualDoc = self.cw.createNetXml(netName, None, False, iface)
+
+        self.assertEqualXml(expectedDoc, actualDoc)
+
+    def testCreateNetXmlBridgedQos(self):
+        netName = "awesome_net"
+        network = "dummy"
+        inbound = {'average': '1024', 'burst': '5000'}
+        expectedDoc = ("""<network>
+                            <name>%s</name>
+                            <forward mode='bridge'/>
+                            <bridge name='%s'/>
+                            <bandwidth>
+                                <inbound average='%s' burst='%s' />
+                            </bandwidth>
+                          </network>"""
+                       % (netName, network,
+                          inbound['average'], inbound['burst']))
+        actualDoc = self.cw.createNetXml(netName, network,
+                                         True, None, qosInbound=inbound)
+
+        self.assertEqualXml(expectedDoc, actualDoc)
diff --git a/vdsm/configNetwork.py b/vdsm/configNetwork.py
index 68025f2..6f69f76 100755
--- a/vdsm/configNetwork.py
+++ b/vdsm/configNetwork.py
@@ -150,7 +150,7 @@
 def addNetwork(network, vlan=None, bonding=None, nics=None, ipaddr=None,
                netmask=None, prefix=None, mtu=None, gateway=None, force=False,
                configWriter=None, bondingOptions=None, bridged=True,
-               _netinfo=None, **options):
+               _netinfo=None, qosInbound=None, qosOutbound=None, **options):
     nics = nics or ()
     if _netinfo is None:
         _netinfo = netinfo.NetInfo()
@@ -198,7 +198,8 @@
                                 gateway, bootproto, _netinfo, configurator,
                                 **options)
     netEnt.configure(**options)
-    configurator.configureLibvirtNetwork(network, netEnt)
+    configurator.configureLibvirtNetwork(network, netEnt, qosInbound,
+                                         qosOutbound)
 
 
 def assertBridgeClean(bridge, vlan, bonding, nics):
diff --git a/vdsm/netconf/ifcfg.py b/vdsm/netconf/ifcfg.py
index 296b042..2c8c2b3 100644
--- a/vdsm/netconf/ifcfg.py
+++ b/vdsm/netconf/ifcfg.py
@@ -18,6 +18,7 @@
 #
 
 from xml.sax.saxutils import escape
+from xml.etree.ElementTree import Element as XmlElement, tostring
 import glob
 import libvirt
 import logging
@@ -109,10 +110,12 @@
                 ifdown(nic.name)
             ifup(nic.name, async)
 
-    def configureLibvirtNetwork(self, network, iface):
+    def configureLibvirtNetwork(self, network, iface, qosInbound=None,
+                                qosOutbound=None):
         self.configWriter.createLibvirtNetwork(network,
                                                isinstance(iface, Bridge),
-                                               iface.name)
+                                               iface.name, qosInbound,
+                                               qosOutbound)
         self._libvirtAdded.add(network)
 
     def configureBonding(self, bond, nics, bridge=None, mtu=None,
@@ -243,18 +246,51 @@
         net.create()
         net.setAutostart(1)
 
+    def createNetXml(self, netName, network, bridged, iface,
+                     qosInbound=None, qosOutbound=None):
+        """
+        Creates Network Xml e.g.:
+        <network>
+            <name>dummy</name>
+            <forward mode='bridge' || 'passthrough'/>
+            <bridge name='awesome'/> || <interface dev='awesome'/>
+            [<inbound average='1000' [peak='5000'] [burst='1024']/>]
+            [<outbound average='1000' burst='1024'/>]
+        </network>
+
+        Forward mode can be either bridge or passthrough,
+        according to net if bridged or bridgeless this
+        determines respectively the presence of bridge
+        or interface element. Inbound or outbound element
+        can be optionally defined.
+        """
+
+        root = XmlElement('network')
+        nameElem = XmlElement('name')
+        nameElem.text = escape(netName)
+        forwardElem = XmlElement('forward',
+                                 mode='bridge' if bridged else 'passthrough')
+        root.append(nameElem)
+        root.append(forwardElem)
+        root.append(XmlElement('bridge', name=escape(network))
+                    if bridged else XmlElement('interface', dev=escape(iface)))
+
+        if qosInbound or qosOutbound:
+            bandwidthElem = XmlElement('bandwidth')
+            if qosInbound:
+                bandwidthElem.append(XmlElement('inbound', **qosInbound))
+            if qosOutbound:
+                bandwidthElem.append(XmlElement('outbound', **qosOutbound))
+            root.append(bandwidthElem)
+
+        return tostring(root)
+
     def createLibvirtNetwork(self, network, bridged=True, iface=None,
-                             skipBackup=False):
+                             skipBackup=False, qosInbound=None,
+                             qosOutbound=None):
         netName = netinfo.LIBVIRT_NET_PREFIX + network
-        if bridged:
-            netXml = '''<network><name>%s</name><forward mode='bridge'/>
-                        <bridge name='%s'/></network>''' % (escape(netName),
-                                                            escape(network))
-        else:
-            netXml = (
-                '''<network><name>%s</name><forward mode='passthrough'>'''
-                '''<interface dev='%s'/></forward></network>''' %
-                (escape(netName), escape(iface)))
+        netXml = self.createNetXml(netName, network, bridged, iface,
+                                   qosInbound, qosOutbound)
         if not skipBackup:
             self._networkBackup(network)
         self._createNetwork(netXml)
@@ -564,7 +600,6 @@
         conf = 'VLAN=yes\n'
         if bridge:
             conf += 'BRIDGE=%s\n' % pipes.quote(bridge)
-
         self._createConfFile(conf, vlan, ipaddr, netmask, gateway,
                              bootproto, mtu, onboot, **kwargs)
 
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index a87dc56..85f63a6 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -63,27 +63,32 @@
 #
 # @bondingOptions:  #optional A string of space-separated <option>=<value> pairs
 #
+# @qosInbound:      #optional VmInterfaceDeviceBandwidthParams for incoming traffic.
+#
+# @qosOutbound:     #optional VmInterfaceDeviceBandwidthParams for outgoing traffic.
+#
 # Since: 4.10.0
 ##
 {'type': 'NetworkOptions',
  'data': {'*ipaddr': 'str', '*netmask': 'str', '*gateway': 'str',
           '*bootproto': 'str', '*delay': 'uint', '*onboot': 'str',
-          '*bondingOptions', 'str'}}
+          '*bondingOptions', 'str', '*qosInbound': 'VmInterfaceDeviceBandwidthParams',
+          '*qosOutbound': 'VmInterfaceDeviceBandwidthParams'}}
 
 ##
 # @Host.addNetwork:
 #
 # Add a new network to this host.
 #
-# @bridge:   The name of the bridge device
+# @bridge:        The name of the bridge device
 #
-# @vlan:     #optional The name of a VLAN to create on the device
+# @vlan:          #optional The name of a VLAN to create on the device
 #
-# @bond:     #optional The name of a bond device to create from @nics
+# @bond:          #optional The name of a bond device to create from @nics
 #
-# @nics:     #optional A list of network device names
+# @nics:          #optional A list of network device names
 #
-# @options:  #optional A @NetworkOptions structure
+# @options:       #optional A @NetworkOptions structure
 #
 # Since: 4.10.0
 ##
@@ -141,35 +146,40 @@
 #
 # Configuration attributes for a single host network.
 #
-# @vlan:       #optional The name of an associated vlan
+# @vlan:          #optional The name of an associated vlan
 #
-# @bonding:    #optional If the network is bonded, the name of the bond device
+# @bonding:       #optional If the network is bonded, the name of the bond device
 #
-# @nic:        #optional If the network is not bonded, an array containing a
-#              single network device name
+# @nic:           #optional If the network is not bonded, an array containing a
+#                 single network device name
 #
-# @ipaddr:     #optional Assign this static IP address to the network
+# @ipaddr:        #optional Assign this static IP address to the network
 #
-# @netmask:    #optional Assign this netmask to the network
+# @netmask:       #optional Assign this netmask to the network
 #
-# @gateway:    #optional Assign this gateway to the network
+# @gateway:       #optional Assign this gateway to the network
 #
-# @bootproto:  #optional Interface autoconfiguration protocol (typically 'dhcp'
-#              or 'static')
+# @bootproto:     #optional Interface autoconfiguration protocol (typically 'dhcp'
+#                 or 'static')
 #
-# @delay:      #optional The time to wait before starting the network device
+# @delay:         #optional The time to wait before starting the network device
 #
-# @onboot:     #optional Start the network device automatically during boot
+# @onboot:        #optional Start the network device automatically during boot
 #
-# @remove:     #optional If True, remove existing network only
+# @remove:        #optional If True, remove existing network only
 #
+# @qosInbound:    #optional VmInterfaceDeviceBandwidthParams for incoming traffic.
+#
+# @qosOutbound:   #optional VmInterfaceDeviceBandwidthParams for outgoing traffic.
+# 
 # Since: 4.10.0
 ##
 {'type': 'SetupNetworkNetAttributes',
  'data': {'*vlan': 'str', '*bonding': 'str', '*nic': ['str'], '*ipaddr': 'str',
           '*netmask': 'str', '*gateway': 'str', '*bootproto': 'str',
-          '*delay': 'uint', '*onboot': 'bool', '*remove': 'bool'}}
-
+          '*delay': 'uint', '*onboot': 'bool', '*remove': 'bool',
+          '*qosInbound': 'VmInterfaceDeviceBandwidthParams',
+          '*qosOutbound': 'VmInterfaceDeviceBandwidthParams'}}
 ##
 # @SetupNetworkBondAttributes:
 #


-- 
To view, visit http://gerrit.ovirt.org/15724
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If0c3b4b9a6fd5eb53579fb2e157b5325caa88d04
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Giuseppe Vallarelli <gvallare at redhat.com>


More information about the vdsm-patches mailing list