Change in vdsm[master]: WIP: Add netcf support

wudxw at linux.vnet.ibm.com wudxw at linux.vnet.ibm.com
Mon Sep 3 14:29:48 UTC 2012


Mark Wu has uploaded a new change for review.

Change subject: WIP: Add netcf support
......................................................................

WIP: Add netcf support

Change-Id: I343364c308654a1f992ee486a005f0ff99d73be8
Signed-off-by: Mark Wu <wudxw at linux.vnet.ibm.com>
---
M vdsm/configNetwork.py
1 file changed, 298 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/15/7715/1

diff --git a/vdsm/configNetwork.py b/vdsm/configNetwork.py
index a4675db..83ad0c3 100755
--- a/vdsm/configNetwork.py
+++ b/vdsm/configNetwork.py
@@ -1135,6 +1135,304 @@
                 del bondings[bond]
 
 
+class Netcf(object):
+
+    def __init__(self):
+        self.doc = xml.dom.minidom.Document()
+        self.conn = libvirtconnection.get()
+
+    def addIfaceType(self, ifaceType, name):
+        inteface = self.doc.createElement('interface')
+        interface.setAttribute('type', ifaceType)
+        interface.setAttribute('name', name)
+        return interface
+
+    def addTopIfaceAttrs(self, topIface, ipaddr=None, netmask=None, gateway=None, mtu=None):
+
+        def toNetmaskBits(netmask):
+            num = int(''.join('%02x' % int(i) for i in netmask.split('.')), 16)
+            bits = 32
+            while num / 2 != 0:
+                if num % 2 == 0:
+                    bits -= 1
+                num /= 2
+            return bits
+
+        start = self.doc.createElement('start')
+        start.setAttribute('onboot', pipes.quote(onboot))
+        interface.appendChild(start)
+
+        mtu = self.doc.createElement('mtu')
+        start.setAttribute('size', mtu)
+        topIface.appendChild(mtu)
+
+        protocal = self.doc.createElement('protocal')
+        protocal.setAttribute('family', "ipv4")
+        if ipaddr:
+            ip = self.doc.createElement('ip')
+            ip.setAttribute('address', (pipes.quote(ipaddr)))
+            prefix = calcNetmaskBits(pipes.quote(netmask))
+            ip.setAttribute('prefix', prefix)
+            protocal.appendChild(ip)
+            if gateway:
+                route = self.doc.createElement('route')
+                route.setAttribute('gateway', (pipes.quote(gateway)))
+                protocal.appendChild(ip)
+        else:
+            dhcp = self.doc.createElement('dhcp')
+            protocal.appendChild(dhcp)
+        topIface.appendChild(protocal)
+
+    def addBridge(self, name, ipaddr=None, netmask=None, mtu=None,
+            gateway=None, bootproto=None, delay='0', onboot='yes', **kwargs):
+        """
+        <interface type="bridge" name="br0">
+          <start mode="onboot"/>
+          <mtu size="1500"/>
+          <protocol family="ipv4">
+            <ip address="192.168.0.5" prefix="24"/>
+            <route gateway="192.168.0.1"/>
+          </protocol>
+          <bridge stp="off" delay="0.01">
+            <interface type="ethernet" name="eth0">
+              <mac address="ab:bb:cc:dd:ee:ff"/>
+            </interface>
+            <interface type="ethernet" name="eth1"/>
+          </bridge>
+        </interface>
+        """
+
+        brIface = self.addIfaceType('bridge', pipes.quote(name))
+        self.addTopIfaceAttrs(brIface, ipaddr, netmask, mtu, gateway)
+        bridge = self.doc.createElement('bridge')
+        bridge.setAttribut('delay', pipes.quote(delay))
+        # fix me need send a patch to allow set 'NM_CONTROLLED=no\n'
+        bridge.appendChild(port)
+        interface.appendChild(bridge)
+
+        """
+          <start mode="onboot"/>
+          <protocol family="ipv4">
+            <dhcp peerdns="no"/>
+          </protocol>
+        """
+    def addBareVlan(self, vlanId, iface):
+        """
+        <interface type="vlan" name="eth0.42">
+          <vlan tag="42">
+            <interface name="eth0"/>
+          </vlan>
+        </interface>
+        """
+        vlanIface = addIfaceType("vlan", iface + '.' + vlanId)
+        if topLevel:
+            vlanIface.appendChild(addTopCommon(onboot, mtu, bootproto))
+        vlanDev = self.doc.createElement("vlan")
+        vlanDev.setAttribute("tag", vlanId)
+        nicIface = self.doc.createElement("interface")
+        nicIface.setAttribute("name", iface)
+        vlanDev.appendChild(nicIface)
+        vlanIface.appendChild(vlanDev)
+        return vlanIface
+
+    def addBareBonding(self, bonding, slaves, bondingOptions=None):
+        """
+        <interface type="bond" name="bond0">
+          <bond mode="active-backup">
+            <arpmon interval="10" target="192.168.122.1"/>
+            <interface type="ethernet" name="eth0">
+              <mac address="ab:bb:cc:dd:ee:ff"/>
+            </interface>
+            <interface type="ethernet" name="eth1"/>
+          </bond>
+        </interface>
+        """
+        doc = xml.dom.minidom.Document()
+        bondIface = self.addIfaceType("bond", bonding)
+        bond = self.doc.createElement('bond')
+        bond.setAttribut('mode', mode)
+        # Todo wudxw: parse bonding options here!!!
+        for slave in slaves:
+            bond.appendChild(slaves)
+        bondIface.appendChild(bond)
+        return bondIface
+
+
+    def addBareNic(self, nic):
+        """
+        <interface type="ethernet" name="eth0">
+          <mac address="ab:bb:cc:dd:ee:ff"/>
+        </interface>
+        """
+        _netinfo = netinfo.NetInfo()
+        hwaddr = _netinfo.nics[nic].get('permhwaddr') or \
+                 _netinfo.nics[nic]['hwaddr']
+
+        nicIface = addInaceType('ethernet', nic)
+        mac = self.doc.createElement('mac')
+        mac.setAttribute('address', hwaddr)
+        return nicIface
+
+    def netcfDefineIface(xmlstr):
+        iface = self.conn.interfaceDefineXML(xmlstr, 0)
+        iface.create()
+
+    def netcfRemoveIface(ifaceName):
+        iface = self.conn.interfaceLookupByName(ifaceName)
+        if iface.isActive():
+            iface.destroy()
+        #self.conn.changeBegin(0)
+        iface.undefine()
+
+        #self.conn.changeCommit(0)
+        #self.conn.changeRollback(0)
+
+    def _createNetwork(self, netXml):
+        conn = libvirtconnection.get()
+        net = conn.networkDefineXML(netXml)
+        net.create()
+        net.setAutostart(1)
+
+    def createLibvirtNetwork(self, network, bridged=True, iface=None,
+                             skipBackup=False):
+        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))
+        if not skipBackup:
+            self._networkBackup(network)
+        self._createNetwork(netXml)
+
+    def _removeNetwork(self, network):
+        netName = netinfo.LIBVIRT_NET_PREFIX + network
+        conn = libvirtconnection.get()
+
+        net = conn.networkLookupByName(netName)
+        if net.isActive():
+            net.destroy()
+        if net.isPersistent():
+            net.undefine()
+
+    def removeLibvirtNetwork(self, network, skipBackup=False):
+        if not skipBackup:
+            self._networkBackup(network)
+        self._removeNetwork(network)
+
+    def _networkBackup(self, network):
+        """Not impolemented now"""
+
+        pass
+
+
+class NetcfConfigurator(Configurator):
+
+    def __init__():
+        self.configWriter = Netcf()
+
+    def addNetwork(self, network, vlan=None, bonding=None, nics=None,
+                   ipaddr=None, netmask=None, mtu=None, gateway=None,
+                   force=False, bondingOptions=None, bridged=True, **options):
+        nics = nics or ()
+        _netinfo = netinfo.NetInfo()
+        bridged = utils.tobool(bridged)
+
+        if mtu:
+            mtu = int(mtu)
+
+        # Validation
+        if not utils.tobool(force):
+            logging.debug('validating network...')
+            _addNetworkValidation(_netinfo, network=network,
+                    vlan=vlan, bonding=bonding, nics=nics, ipaddr=ipaddr,
+                    netmask=netmask, gateway=gateway, bondingOptions=bondingOptions,
+                    bridged=bridged, **options)
+
+        logging.info("Adding network %s with vlan=%s, bonding=%s, nics=%s,"
+                     " bondingOptions=%s, mtu=%s, bridged=%s, options=%s",
+                     network, vlan, bonding, nics, bondingOptions,
+                     mtu, bridged, options)
+
+        prevmtu = None
+        if mtu and vlan:
+            #Todo, implement getMaxMtu for netcf configurator
+            prevmtu = configWriter.getMaxMtu(nics, mtu)
+
+        nic = nics[0] if nics else None
+        iface = bonding or nic
+
+        # take down nics that need to be changed
+        vlanedIfaces = [v['iface'] for v in _netinfo.vlans.values()]
+        if bonding not in vlanedIfaces:
+            for nic in nics:
+                if nic not in vlanedIfaces:
+                    ifdown(nic)
+
+        if bridged:
+            ifdown(network)
+
+        slaves = []
+        for nic in nicSort(nics):
+            topInface = self.addNic(nic)
+            slaves.append(topIface)
+        if bonding:
+            topIface = self.configWriter.addBareBonding(bonding, slaves, bondingOption)
+        if vlan:
+            topIface = self.configWriter.addBareVlan(vlan, topIface)
+        if bridged:
+            topIface = self.configWriter.addBridge(network, port=topIface, ipaddr=ipaddr, netmask=netmask,
+                                    mtu=mtu, gateway=gateway, **options)
+        else:
+            self.configWriter.addTopIfaceAttrs(topIface, ipaddr=ipaddr, netmask=netmask, mtu=mtu, gateway=gateway)
+
+        topIfaceXml = self.configWriter.netcfDefineIface(topIface.toprettyxml(encoding='utf-8'))
+        self.configWriter.netcfDefineIface(topIfaceXml, 0)
+
+        if bridged:
+            if options.get('bootproto') == 'dhcp' and not utils.tobool(options.get('blockingdhcp')):
+                # wait for dhcp in another thread, so vdsm won't get stuck (BZ#498940)
+                t = threading.Thread(target=self.configWriter.netcfCreateIface, name='ifup-waiting-on-dhcp', args=(network,))
+                t.daemon = True
+                t.start()
+            else:
+                self.configWriter.netcfCreateIface(network)
+        # add libvirt network
+        createLibvirtNetwork(network, bridged, iface)
+
+
+    def delNetworkNetcf(self, network, vlan=None, bonding=None, nics=None, force=False,
+                   implicitBonding=True, **options):
+        _netinfo = netinfo.NetInfo()
+
+        if network not in _netinfo.networks:
+            logging.info("Network %r: doesn't exist in libvirt database", network)
+            if network in netinfo.bridges():
+                self.configWriter.removeBridge(network)
+            else:
+                raise ConfigNetworkError(ne.ERR_BAD_BRIDGE,
+                        "Cannot delete network %r: It doesn't exist "
+                        "in the system" % network)
+
+            if vlan:
+                self.configWriter.removeVlan(vlan, bonding or nics[0])
+
+            return
+
+
+        removeLibvirtNetwork(network, log=False)
+        # We need to gather NetInfo again to refresh networks info from libvirt.
+        # The deleted bridge should never be up at this stage.
+        if network in netinfo.NetInfo().networks:
+            raise ConfigNetworkError(ne.ERR_USED_BRIDGE,
+                    "delNetwork: bridge %s still exists" % network)
+
+        self.configWriter.netcfRemoveIface(network)
+
+
 configurator = NativeConfigurator()
 
 


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I343364c308654a1f992ee486a005f0ff99d73be8
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Mark Wu <wudxw at linux.vnet.ibm.com>


More information about the vdsm-patches mailing list