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 <[email protected]> --- 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 <[email protected]> _______________________________________________ vdsm-patches mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches
