From 21a53b9ba7790df9c93a583217a81afceb761091 Mon Sep 17 00:00:00 2001 From: Alon Kochba Date: Mon, 13 Feb 2017 11:55:01 +0200 Subject: [PATCH] Fix regression in auto tunnels - listen on Interface This patch https://git.opendaylight.org/gerrit/49908 introduced a behavior change in how parentRefs are used. Refactor the auto-tunnel behavior to listen on Interface from config instead of Interface State, to take into account any change in parentRefs and in any order. Change-Id: Iee459634fab97eba5f76dbe7ae70caa00a48f3b4 Signed-off-by: Alon Kochba --- ...BridgeRefEntryToTransportZoneListener.java | 4 +- ... => InterfaceToTransportZoneListener.java} | 22 +- .../TransportZoneNotificationUtil.java | 154 +++---- .../org/opendaylight/blueprint/neutronvpn.xml | 4 +- .../neutronvpn/ToTransportZoneTest.java | 395 ------------------ 5 files changed, 79 insertions(+), 500 deletions(-) rename vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/{InterfaceStateToTransportZoneListener.java => InterfaceToTransportZoneListener.java} (74%) delete mode 100644 vpnservice/neutronvpn/neutronvpn-impl/src/test/java/org/opendaylight/netvirt/neutronvpn/ToTransportZoneTest.java diff --git a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/BridgeRefEntryToTransportZoneListener.java b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/BridgeRefEntryToTransportZoneListener.java index 04d8565b86..7a166093dc 100644 --- a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/BridgeRefEntryToTransportZoneListener.java +++ b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/BridgeRefEntryToTransportZoneListener.java @@ -55,13 +55,13 @@ public class BridgeRefEntryToTransportZoneListener extends AsyncDataTreeChangeLi protected void update(InstanceIdentifier identifier, BridgeRefEntry original, BridgeRefEntry update) { LOG.debug("handle BridgeRefEntry update notification {}", update); - ism.updateTrasportZone(update); + ism.updateTransportZone(update); } @Override protected void add(InstanceIdentifier identifier, BridgeRefEntry add) { LOG.debug("handle BridgeRefEntry add notification {}", add); - ism.updateTrasportZone(add); + ism.updateTransportZone(add); } @Override diff --git a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/InterfaceStateToTransportZoneListener.java b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/InterfaceToTransportZoneListener.java similarity index 74% rename from vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/InterfaceStateToTransportZoneListener.java rename to vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/InterfaceToTransportZoneListener.java index 4fe2e680b4..931593baba 100644 --- a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/InterfaceStateToTransportZoneListener.java +++ b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/InterfaceToTransportZoneListener.java @@ -11,22 +11,22 @@ import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeLis import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class InterfaceStateToTransportZoneListener - extends AsyncDataTreeChangeListenerBase +public class InterfaceToTransportZoneListener + extends AsyncDataTreeChangeListenerBase implements ClusteredDataTreeChangeListener, AutoCloseable { - private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateToTransportZoneListener.class); + private static final Logger LOG = LoggerFactory.getLogger(InterfaceToTransportZoneListener.class); private TransportZoneNotificationUtil ism; private DataBroker dbx; - public InterfaceStateToTransportZoneListener(DataBroker dbx, NeutronvpnManager nvManager) { - super(Interface.class, InterfaceStateToTransportZoneListener.class); + public InterfaceToTransportZoneListener(DataBroker dbx, NeutronvpnManager nvManager) { + super(Interface.class, InterfaceToTransportZoneListener.class); ism = new TransportZoneNotificationUtil(dbx, nvManager); this.dbx = dbx; } @@ -34,13 +34,13 @@ public class InterfaceStateToTransportZoneListener public void start() { LOG.info("{} start", getClass().getSimpleName()); if (ism.isAutoTunnelConfigEnabled()) { - registerListener(LogicalDatastoreType.OPERATIONAL, dbx); + registerListener(LogicalDatastoreType.CONFIGURATION, dbx); } } @Override protected InstanceIdentifier getWildCardPath() { - return InstanceIdentifier.create(InterfacesState.class).child(Interface.class); + return InstanceIdentifier.create(Interfaces.class).child(Interface.class); } @@ -61,8 +61,8 @@ public class InterfaceStateToTransportZoneListener } @Override - protected InterfaceStateToTransportZoneListener getDataTreeChangeListener() { - return InterfaceStateToTransportZoneListener.this; + protected InterfaceToTransportZoneListener getDataTreeChangeListener() { + return InterfaceToTransportZoneListener.this; } } diff --git a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/TransportZoneNotificationUtil.java b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/TransportZoneNotificationUtil.java index ca79ca46de..d12363c235 100644 --- a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/TransportZoneNotificationUtil.java +++ b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/TransportZoneNotificationUtil.java @@ -11,7 +11,6 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Set; - import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.mdsalutil.MDSALUtil; @@ -19,8 +18,8 @@ import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils; import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry; @@ -43,13 +42,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neu import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVxlan; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -84,7 +78,7 @@ public class TransportZoneNotificationUtil { * its TZ * @param entry - the BridgeEntryRef that was updated */ - public void updateTrasportZone(BridgeRefEntry entry) { + public void updateTransportZone(BridgeRefEntry entry) { BigInteger dpid = entry.getDpid(); Set allRouterDpnList = NeutronvpnUtils.getAllRouterDpnList(dataBroker, dpid); for (RouterDpnList routerDpnList : allRouterDpnList) { @@ -93,42 +87,59 @@ public class TransportZoneNotificationUtil { } /** - * Update/add TransportZone for interface State inter.
- * If Transport zone for given Network doesn't exist, then it will be added.
+ * Update/add TransportZone for interface config. + * If Transport zone for given Network doesn't exist, then it will be added. * If the TEP of the port's node exists in the TZ, it will not be added. - * @param inter - the interface to update + * @param iface - the interface to update */ // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") - public void updateTransportZone(Interface inter) { - List ports = getPortsFromInterface(inter); - //supports VPN aware VMs (multiple ports for one interface) - for (Port port : ports) { - try { - - if (!checkIfVxlanNetwork(port)) { - continue; - } + public void updateTransportZone(Interface iface) { + try { + Uuid portUid = new Uuid(iface.getName()); + Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portUid); - String subnetIp = ALL_SUBNETS; - BigInteger dpnId = getDpnIdFromInterfaceState(inter); + if (!checkIfVxlanNetwork(port)) { + return; + } + String subnetIp = ALL_SUBNETS; - InstanceIdentifier inst = InstanceIdentifier.create(TransportZones.class) - .child(TransportZone.class, new TransportZoneKey(port.getNetworkId().getValue())); - TransportZone zone = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, inst); + ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class); + if (parentRefs == null || parentRefs.getParentInterface() == null) { + // If parentRefs are missing, try to find a matching parent and update - this will trigger another DCN + LOG.debug("parentRef is missing for interface {}, skipping update of transport zone"); + return; + } - if (zone == null) { - zone = createZone(subnetIp, port.getNetworkId().getValue()); - } + // FIXME Use IInterfaceManager getInterfaceInfoFromConfigDataStore when refactoring into ELAN + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state + .Interface ifState = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, + buildStateInterfaceId(parentRefs.getParentInterface())); - if (addVtep(zone, subnetIp, dpnId) > 0) { - addTransportZone(zone, inter.getName()); - } + if (ifState == null) { + LOG.debug("ifState is missing for parentRef {} of interface {}, skipping update of transport zone", + parentRefs.getParentInterface(), iface.getName()); + return; + } - } catch (Exception e) { - LOG.warn("failed to add tunnels on interface added to subnet {}. ", inter, e); + BigInteger dpnId = getDpnIdFromInterfaceState(ifState); + + + InstanceIdentifier inst = InstanceIdentifier.create(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(port.getNetworkId().getValue())); + TransportZone zone = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, inst); + + if (zone == null) { + zone = createZone(subnetIp, port.getNetworkId().getValue()); + } + + if (addVtep(zone, subnetIp, dpnId) > 0) { + addTransportZone(zone, iface.getName()); } + + } catch (Exception e) { + LOG.warn("failed to add tunnels on interface added to subnet {}. ", iface, e); } } @@ -178,10 +189,7 @@ public class TransportZoneNotificationUtil { } private boolean checkIfVxlanNetwork(Port port) { - InstanceIdentifier networkPath = InstanceIdentifier.create(Neutron.class) - .child(Networks.class).child(Network.class, new NetworkKey(port.getNetworkId())); - Network network = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, networkPath); - + Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, port.getNetworkId()); if (network == null || !NeutronvpnUtils.isNetworkOfType(network, NetworkTypeVxlan.class)) { LOG.debug("port in non-VXLAN network " + port.getName()); return false; @@ -191,63 +199,14 @@ public class TransportZoneNotificationUtil { } - private BigInteger getDpnIdFromInterfaceState(Interface inter) { - String lowerLayerIf = inter.getLowerLayerIf().get(0); + private BigInteger getDpnIdFromInterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf + .interfaces.rev140508.interfaces.state.Interface ifState) { + String lowerLayerIf = ifState.getLowerLayerIf().get(0); NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf); BigInteger dpId = new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId)); return dpId; } - /* - * takes all Neutron Ports that are related to the given interface state - * @param interfaceState - interface state to update - * @return - list of ports bound to interface - */ - private List getPortsFromInterface(Interface interfaceState) { - String physPortId = getPortFromInterfaceName(interfaceState.getName()); - List portsList = new ArrayList<>(); - - InstanceIdentifier interPath = InstanceIdentifier.create(Interfaces.class); - Interfaces interfaces = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, interPath); - if (interfaces == null) { - LOG.error("No interfaces in configuration"); - return portsList; - } - List inters = interfaces.getInterface(); - - // take all interfaces with parent-interface with physPortId name - for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces - .Interface inter : inters) { - ParentRefs parent = inter.getAugmentation(ParentRefs.class); - if (parent == null || !physPortId.equals(parent.getParentInterface())) { - continue; - } - String parentInt = inter.getName(); - Uuid portUid = new Uuid(parentInt); - InstanceIdentifier pathPort = InstanceIdentifier.create(Neutron.class).child(Ports.class) - .child(Port.class, new PortKey(portUid)); - Port port = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, pathPort); - - if (port == null) { - LOG.debug("got Interface State of non NeutronPort instance " + physPortId); - continue; - } - - portsList.add(port); - } - - return portsList; - } - - - private String getPortFromInterfaceName(String name) { - String[] splitedStr = name.split(OF_URI_SEPARATOR); - name = splitedStr.length > 1 ? splitedStr[1] : name; - return name; - } - - // TODO: code is used in another places. Should be extracted into utility private String getDpnFromNodeConnectorId(NodeConnectorId portId) { String[] split = portId.getValue().split(OF_URI_SEPARATOR); @@ -360,4 +319,19 @@ public class TransportZoneNotificationUtil { return node; } + + // FIXME Remove this, duplicated from IfmUtil + public static final InstanceIdentifier buildStateInterfaceId(String interfaceName) { + InstanceIdentifier.InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(InterfacesState.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces + .rev140508.interfaces.state.Interface.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces + .rev140508.interfaces.state.InterfaceKey(interfaceName)); + InstanceIdentifier id = idBuilder.build(); + return id; + } } diff --git a/vpnservice/neutronvpn/neutronvpn-impl/src/main/resources/org/opendaylight/blueprint/neutronvpn.xml b/vpnservice/neutronvpn/neutronvpn-impl/src/main/resources/org/opendaylight/blueprint/neutronvpn.xml index 8166a4539d..9149ce1588 100644 --- a/vpnservice/neutronvpn/neutronvpn-impl/src/main/resources/org/opendaylight/blueprint/neutronvpn.xml +++ b/vpnservice/neutronvpn/neutronvpn-impl/src/main/resources/org/opendaylight/blueprint/neutronvpn.xml @@ -159,8 +159,8 @@ - diff --git a/vpnservice/neutronvpn/neutronvpn-impl/src/test/java/org/opendaylight/netvirt/neutronvpn/ToTransportZoneTest.java b/vpnservice/neutronvpn/neutronvpn-impl/src/test/java/org/opendaylight/netvirt/neutronvpn/ToTransportZoneTest.java deleted file mode 100644 index 9f0291de94..0000000000 --- a/vpnservice/neutronvpn/neutronvpn-impl/src/test/java/org/opendaylight/netvirt/neutronvpn/ToTransportZoneTest.java +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (c) 2015 - 2016 HPE and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.netvirt.neutronvpn; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; - -import com.google.common.base.Optional; -import com.google.common.util.concurrent.Futures; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.runners.MockitoJUnitRunner; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeBase; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVxlan; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension; -import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtensionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsBuilder; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -@RunWith(MockitoJUnitRunner.class) -public class ToTransportZoneTest { - - private static final String PHYS_PORT_NAME = "tap12345-67"; - private static final Long DPN_ID = 1234567890L; - private static final BigInteger DPN_ID_2 = BigInteger.valueOf(1234567891L); - private static final String PORT_NAME = "12345678-1234-1234-1234-123456789012"; - private static final String PORT_IP = "1.1.1.1"; - private static final String NETWORK_ID = "12345678-1234-1234-1234-123456789012"; - private static final String SUBNET = "0.0.0.0/0"; - private static final String OVS_IP = "10.0.0.1"; - private static final IpAddress OVS_IP_2 = new IpAddress("10.0.0.2".toCharArray()); - private static final String VTEP_PORT = "tunnel_port"; - private static final String ROUTER_ID = "10345678-1234-1234-1234-123456789012"; - - @Mock - private DataBroker dataBroker; - @Mock - private NeutronvpnManager neutronvpnManager; - @Mock - private ListenerRegistration dataChangeListenerRegistration; - @Mock - private WriteTransaction mockWriteTx; - @Mock - private ReadOnlyTransaction mockReadTx; - @Mock - private Node node; - private Interfaces interf; - private Port port; - private List expectedVteps = new ArrayList<>(); - InterfaceStateToTransportZoneListener interfaceStateToTransportZoneChangeListener; - NeutronRouterDpnsToTransportZoneListener neutronRouterDpnsToTransportZoneListener; - private Network network; - - @Before - public void setUp() { - when(dataBroker.registerDataChangeListener(any(LogicalDatastoreType.class), // - any(InstanceIdentifier.class), // - any(DataChangeListener.class), // - any(AsyncDataBroker.DataChangeScope.class))). // - thenReturn(dataChangeListenerRegistration); - doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction(); - doAnswer(invocation -> { - testTZ(invocation); - return null; - }).when(mockWriteTx).put(any(), any(), any(), any(Boolean.class)); - doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit(); - doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction(); - - Subnetmap subnetMap = new SubnetmapBuilder().setSubnetIp(SUBNET).build(); - - when(neutronvpnManager.updateSubnetmapNodeWithPorts(any(Uuid.class), any(Uuid.class), any(Uuid.class))) - .thenReturn(subnetMap); - - when(mockReadTx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))) - .thenReturn(Futures.immediateCheckedFuture(Optional.absent())); - interfaceStateToTransportZoneChangeListener = - new InterfaceStateToTransportZoneListener(dataBroker, neutronvpnManager); - neutronRouterDpnsToTransportZoneListener = - new NeutronRouterDpnsToTransportZoneListener(dataBroker, neutronvpnManager); - } - - @After - public void afterTestCleanup() { - expectedVteps.clear(); - } - - @Test - public void addInterfaceState_FirstTZ() throws Exception { - List interfaces = new ArrayList<>(); - interfaces.add(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508 - .interfaces.InterfaceBuilder().setName(PORT_NAME) - .addAugmentation(ParentRefs.class, new ParentRefsBuilder().setParentInterface(PHYS_PORT_NAME).build()) - .build()); - interf = new InterfacesBuilder().setInterface(interfaces).build(); - port = buildPort(PORT_IP); - buildNode(); - when(mockReadTx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(interf))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(port))) - .thenReturn(Futures.immediateCheckedFuture(Optional.absent())) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(getBridgeRefForNode()))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(node))) - .thenReturn(Futures.immediateCheckedFuture(Optional.absent())); - InterfaceBuilder intBuilder = new InterfaceBuilder(); - intBuilder.setName(PHYS_PORT_NAME); - intBuilder.setLowerLayerIf(new ArrayList<>(Arrays.asList(new String[] {"int:" + DPN_ID}))); - //NetworkId(new Uuid("12345678-1234-1234-1234-123456789012")); - expectedVteps.add(buildVtep(BigInteger.valueOf(DPN_ID), new IpAddress(OVS_IP.toCharArray()), VTEP_PORT)); - interfaceStateToTransportZoneChangeListener.add(InstanceIdentifier.create(Interface.class), intBuilder.build()); - } - - @Test - public void addInterfaceState_ExistingTZ() throws Exception { - List interfaces = new ArrayList<>(); - interfaces.add(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508 - .interfaces.InterfaceBuilder().setName(PORT_NAME) - .addAugmentation(ParentRefs.class, new ParentRefsBuilder().setParentInterface(PHYS_PORT_NAME).build()) - .build()); - interf = new InterfacesBuilder().setInterface(interfaces).build(); - port = buildPort(PORT_IP); - network = buildNetwork(NetworkTypeVxlan.class); - TransportZone tz = new TransportZoneBuilder().setZoneName(NETWORK_ID) - .setTunnelType(TunnelTypeVxlan.class).setSubnets(new ArrayList<>()).build(); - buildNode(); - when(mockReadTx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(interf))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(port))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(network))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(tz))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(getBridgeRefForNode()))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(node))) - .thenReturn(Futures.immediateCheckedFuture(Optional.absent())); - InterfaceBuilder intBuilder = new InterfaceBuilder(); - intBuilder.setName(PHYS_PORT_NAME); - intBuilder.setLowerLayerIf(new ArrayList<>(Arrays.asList(new String[] {"int:" + DPN_ID}))); - //NetworkId(new Uuid("12345678-1234-1234-1234-123456789012")); - expectedVteps.add(buildVtep(BigInteger.valueOf(DPN_ID), new IpAddress(OVS_IP.toCharArray()), VTEP_PORT)); - interfaceStateToTransportZoneChangeListener.add(InstanceIdentifier.create(Interface.class), - intBuilder.build()); - } - - @Test - public void addInterfaceState_MultipleVtepsInTZ() throws Exception { - List interfaces = new ArrayList<>(); - interfaces.add(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508 - .interfaces.InterfaceBuilder().setName(PORT_NAME) - .addAugmentation(ParentRefs.class, new ParentRefsBuilder().setParentInterface(PHYS_PORT_NAME).build()) - .build()); - interf = new InterfacesBuilder().setInterface(interfaces).build(); - port = buildPort(PORT_IP); - network = buildNetwork(NetworkTypeVxlan.class); - TransportZone tz = new TransportZoneBuilder().setZoneName(NETWORK_ID) - .setTunnelType(TunnelTypeVxlan.class).setSubnets(new ArrayList<>()).build(); - buildNode(); - when(mockReadTx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(interf))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(port))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(network))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(tz))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(getBridgeRefForNode()))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(node))) - .thenReturn(Futures.immediateCheckedFuture(Optional.absent())); - InterfaceBuilder intBuilder = new InterfaceBuilder(); - intBuilder.setName(PHYS_PORT_NAME); - intBuilder.setLowerLayerIf(new ArrayList<>(Arrays.asList(new String[] {"int:" + DPN_ID}))); - //NetworkId(new Uuid("12345678-1234-1234-1234-123456789012")); - expectedVteps.add(buildVtep(BigInteger.valueOf(DPN_ID), new IpAddress(OVS_IP.toCharArray()), VTEP_PORT)); - interfaceStateToTransportZoneChangeListener.add(InstanceIdentifier.create(Interface.class), - intBuilder.build()); - } - - @Test - public void addInterfaceState_VLAN_Network() throws Exception { - List interfaces = new ArrayList<>(); - interfaces.add(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508 - .interfaces.InterfaceBuilder().setName(PORT_NAME) - .addAugmentation(ParentRefs.class, new ParentRefsBuilder().setParentInterface(PHYS_PORT_NAME).build()) - .build()); - interf = new InterfacesBuilder().setInterface(interfaces).build(); - port = buildPort(PORT_IP); - network = buildNetwork(NetworkTypeVlan.class); - TransportZone tz = new TransportZoneBuilder().setZoneName(NETWORK_ID) - .setTunnelType(TunnelTypeVxlan.class).setSubnets(buildSubnets()).build(); - buildNode(); - when(mockReadTx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(interf))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(port))) - .thenReturn(Futures.immediateCheckedFuture(Optional.of(network))); - InterfaceBuilder intBuilder = new InterfaceBuilder(); - intBuilder.setName(PHYS_PORT_NAME); - intBuilder.setLowerLayerIf(new ArrayList<>(Arrays.asList(new String[] {"int:" + DPN_ID}))); - //NetworkId(new Uuid("12345678-1234-1234-1234-123456789012")); - interfaceStateToTransportZoneChangeListener.add(InstanceIdentifier.create(Interface.class), intBuilder.build()); - } - - @Test - public void addRouter() throws Exception { - when(mockReadTx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))) - .thenReturn(Futures.immediateCheckedFuture(Optional.absent())); - RouterDpnListBuilder intBuilder = new RouterDpnListBuilder(); - RouterDpnList routerDpnList = buildRouterDpnList(); - expectedVteps.add(buildVtep(BigInteger.valueOf(DPN_ID), new IpAddress(OVS_IP.toCharArray()), VTEP_PORT)); - expectedVteps.add(buildVtep(DPN_ID_2, OVS_IP_2, VTEP_PORT)); - neutronRouterDpnsToTransportZoneListener.add(InstanceIdentifier.create(RouterDpnList.class), routerDpnList); - } - - private RouterDpnList buildRouterDpnList() { - RouterDpnListBuilder routerDpnBuilder = new RouterDpnListBuilder(); - routerDpnBuilder.setRouterId(ROUTER_ID); - List list = new ArrayList<>(); - list.add(new DpnVpninterfacesListBuilder().setDpnId(BigInteger.valueOf(DPN_ID)).build()); - list.add(new DpnVpninterfacesListBuilder().setDpnId(DPN_ID_2).build()); - routerDpnBuilder.setDpnVpninterfacesList(list); - return routerDpnBuilder.build(); - } - - private Network buildNetwork(Class networkType) { - NetworkBuilder builder = new NetworkBuilder(); - NetworkProviderExtensionBuilder augBuilder = new NetworkProviderExtensionBuilder(); - augBuilder.setNetworkType(networkType); - builder.addAugmentation(NetworkProviderExtension.class, augBuilder.build()); - return builder.build(); - } - - private List buildSubnets() { - SubnetsBuilder subnetsBuilder = new SubnetsBuilder(); - List vteps = new ArrayList<>(); - - vteps.add(buildVtep(DPN_ID_2, OVS_IP_2, VTEP_PORT)); - subnetsBuilder.setVteps(vteps); - subnetsBuilder.setPrefix(new IpPrefix(SUBNET.toCharArray())); - List subnets = new ArrayList<>(); - subnets.add(subnetsBuilder.build()); - return subnets; - } - - private Vteps buildVtep(BigInteger dpnId, IpAddress portIp, String portName) { - VtepsBuilder vtepBuilder = new VtepsBuilder(); - vtepBuilder.setDpnId(dpnId); - vtepBuilder.setIpAddress(portIp); - vtepBuilder.setPortname(portName); - return vtepBuilder.build(); - } - - - private BridgeRefEntry getBridgeRefForNode() { - BridgeRefEntryBuilder breb = new BridgeRefEntryBuilder(); - InstanceIdentifier path = - InstanceIdentifier.create(Node.class).augmentation(OvsdbBridgeAugmentation.class); - breb.setBridgeReference(new OvsdbBridgeRef(path)); - return breb.build(); - } - - private void buildNode() { - List list = new ArrayList<>(); - list.add(new OpenvswitchOtherConfigsBuilder().setOtherConfigKey("local_ip") - .setOtherConfigValue(OVS_IP).build()); - OvsdbNodeAugmentation ovsdbNode = new OvsdbNodeAugmentationBuilder().setOpenvswitchOtherConfigs(list).build(); - when(node.getAugmentation(OvsdbNodeAugmentation.class)).thenReturn(ovsdbNode); - } - - private Port buildPort(String portIp) { - PortBuilder portBuilder = new PortBuilder(); - portBuilder.setFixedIps(new ArrayList<>(Arrays.asList(new FixedIps[] - {new FixedIpsBuilder().setIpAddress(new IpAddress(portIp.toCharArray())).build()}))); - portBuilder.setNetworkId(new Uuid(NETWORK_ID)); - return portBuilder.build(); - } - - protected void testTZ(InvocationOnMock invocation) { - TransportZones tzs = (TransportZones) invocation.getArguments()[2]; - assertNotNull(tzs); - List tzList = tzs.getTransportZone(); - assertNotNull(tzList); - assertEquals(1, tzList.size()); - TransportZone tz = tzList.get(0); - assertTZ(tz); - } - - private void assertTZ(TransportZone tz) { - assertSubnets(tz.getSubnets()); - assertTunnelType(tz.getTunnelType()); - assertZoneName(tz.getZoneName()); - } - - - private void assertZoneName(String zoneName) { - assertEquals(NETWORK_ID, zoneName); - } - - - private void assertTunnelType(Class tunnelType) { - assertEquals(TunnelTypeVxlan.class, tunnelType); - } - - - private void assertSubnets(List subnets) { - assertNotNull(subnets); - assertEquals(1, subnets.size()); - assertSubnet(subnets.get(0)); - } - - - private void assertSubnet(Subnets subnets) { - assertEquals(new IpPrefix(SUBNET.toCharArray()), subnets.getPrefix()); - assertNotNull(subnets.getVteps()); - assertVtep(expectedVteps, subnets.getVteps()); - } - - private void assertVtep(List expectedVteps, List vteps) { - assertNotNull(vteps); - assertEquals(expectedVteps.size(), vteps.size()); - outer_loop: - for (Vteps expectedVtep : expectedVteps) { - for (Vteps vtep : vteps) { - boolean flag = true; - flag &= expectedVtep.getDpnId().equals(vtep.getDpnId()); - flag &= expectedVtep.getIpAddress().equals(vtep.getIpAddress()); - flag &= expectedVtep.getPortname().equals(vtep.getPortname()); - if (flag) { - continue outer_loop; - } - } - fail(); - } - } -} -- 2.36.6