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