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