X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=neutronvpn%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Fneutronvpn%2FNeutronPortChangeListener.java;h=5f4f768338c53dcc3c6d6df101fc187db3938d2b;hb=2f0569ed75ef8a1fb60f992d19c8bbdf92ff45bf;hp=13fbb7fea781477fa1a7320fe930f7e6ac300fe2;hpb=716d996db88a6aecbed4cee531d308fe0d7f7086;p=netvirt.git diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java index 13fbb7fea7..5f4f768338 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java @@ -9,8 +9,8 @@ package org.opendaylight.netvirt.neutronvpn; import static org.opendaylight.genius.infra.Datastore.CONFIGURATION; -import com.google.common.base.Optional; import com.google.common.base.Strings; +import com.google.common.util.concurrent.ListenableFuture; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -23,15 +23,15 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; import javax.inject.Singleton; import org.apache.commons.lang3.ObjectUtils; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; -import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar; import org.opendaylight.genius.infra.Datastore; @@ -40,17 +40,27 @@ import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; import org.opendaylight.genius.infra.TypedWriteTransaction; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; +import org.opendaylight.infrautils.utils.concurrent.Executors; import org.opendaylight.infrautils.utils.concurrent.ListenableFutures; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.ReadFailedException; import org.opendaylight.netvirt.elanmanager.api.IElanService; import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice; import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants; import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan; +import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan; 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.interfaces.rev140508.interfaces.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.rev160406.IfL2vlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder; +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.SplitHorizon; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizonBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs; @@ -63,6 +73,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubport; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig; @@ -77,7 +89,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton -public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase { +public class NeutronPortChangeListener extends AbstractAsyncDataTreeChangeListener { private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class); private final DataBroker dataBroker; private final ManagedNewTransactionRunner txRunner; @@ -89,7 +101,9 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

getWildCardPath() { - return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class); } @Override - protected NeutronPortChangeListener getDataTreeChangeListener() { - return NeutronPortChangeListener.this; + @PreDestroy + public void close() { + super.close(); + Executors.shutdownAndAwaitTermination(getExecutorService()); } - @Override - protected void add(InstanceIdentifier identifier, Port input) { + public void add(InstanceIdentifier identifier, Port input) { + LOG.trace("Received port add event: port={}", input); String portName = input.getUuid().getValue(); LOG.trace("Adding Port : key: {}, value={}", identifier, input); Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId()); @@ -151,7 +164,7 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

identifier, Port input) { + public void remove(InstanceIdentifier identifier, Port input) { LOG.trace("Removing Port : key: {}, value={}", identifier, input); Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId()); // need to proceed with deletion in case network is null for a case where v2 sync happens and a read for @@ -191,6 +204,7 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

identifier, Port original, Port update) { + public void update(InstanceIdentifier identifier, Port original, Port update) { + LOG.trace("Received port update event: original={}, update={}", original, update); // Switchdev ports need to be bounded to a host before creation // in order to validate the supported vnic types from the hostconfig if (isPortTypeSwitchdev(original) @@ -210,7 +225,6 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(portName); - jobCoordinator.enqueueJob("PORT- " + portName, - () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, + jobCoordinator.enqueueJob("PORT- " + portName, () -> { + ListenableFuture future = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> { - Optional optionalInf = - confTx.read(interfaceIdentifier).get(); + Optional optionalInf = confTx.read(interfaceIdentifier).get(); if (optionalInf.isPresent()) { InterfaceBuilder interfaceBuilder = new InterfaceBuilder(optionalInf.get()); - InterfaceAcl infAcl = handlePortSecurityUpdated(original, update, - origSecurityEnabled, updatedSecurityEnabled, interfaceBuilder).build(); - interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl); + if (origSecurityEnabled || updatedSecurityEnabled) { + InterfaceAcl infAcl = handlePortSecurityUpdated(original, update, origSecurityEnabled, + updatedSecurityEnabled, interfaceBuilder).build(); + interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl); + } else if (isDhcpServerPort) { + Set oldIPs = getFixedIpSet(original.getFixedIps()); + Set newIPs = getFixedIpSet(update.getFixedIps()); + if (!oldIPs.equals(newIPs)) { + InterfaceAcl infAcl = neutronvpnUtils.getDhcpInterfaceAcl(update); + interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl); + } + } LOG.info("update: Of-port-interface updation for port {}", portName); // Update OFPort interface for this neutron port confTx.put(interfaceIdentifier, interfaceBuilder.build()); } else { LOG.warn("update: Interface {} is not present", portName); } - }))); + }); + ListenableFutures.addErrorLogging(future, LOG, + "update: Failed to update interface {} with networkId {}", portName, network); + return Collections.singletonList(future); + }); } } - private void handleFloatingIpPortUpdated(Port original, Port update) { - if ((original == null || original.getDeviceId().equals(NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING)) - && !update.getDeviceId().equals(NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING)) { + private void handleFloatingIpPortUpdated(@Nullable Port original, Port update) { + if ((original == null || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(original.getDeviceId())) + && !NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(update.getDeviceId())) { // populate floating-ip uuid and floating-ip port attributes (uuid, mac and subnet id for the ONLY // fixed IP) to be used by NAT, depopulated in NATService once mac is retrieved in the removal path addToFloatingIpPortInfo(new Uuid(update.getDeviceId()), update.getUuid(), update.getFixedIps().get(0) @@ -292,9 +319,8 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

subnetMapList = new ArrayList<>(); - List portIps = routerPort.getFixedIps(); boolean portIsIpv6 = false; - for (FixedIps portIP : portIps) { + for (FixedIps portIP : routerPort.nonnullFixedIps()) { // NOTE: Please donot change the order of calls to updateSubnetNodeWithFixedIP // and addSubnetToVpn here if (internetVpnId != null @@ -310,24 +336,21 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

{ nvpnNatManager.handleSubnetsForExternalRouter(routerId); @@ -360,8 +388,9 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

portIps = routerPort.getFixedIps(); + Uuid vpnId = ObjectUtils.defaultIfNull(neutronvpnUtils.getVpnForRouter(routerId, true), + routerId); + List portIps = routerPort.nonnullFixedIps(); boolean vpnInstanceInternetIpVersionRemoved = false; Uuid vpnInstanceInternetUuid = null; for (FixedIps portIP : portIps) { @@ -388,21 +417,20 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

{ - boolean vpnInstanceIpVersionRemoved = false; - IpVersionChoice vpnInstanceIpVersionToRemove = IpVersionChoice.UNDEFINED; + IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; for (FixedIps portIP : portIps) { Subnetmap sn = neutronvpnUtils.getSubnetmap(portIP.getSubnetId()); - // router Port have either IPv4 or IPv6, never both - if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) { - vpnInstanceIpVersionRemoved = true; - vpnInstanceIpVersionToRemove = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()); + if (null == sn) { + LOG.error("Subnetmap for subnet {} not found", portIP.getSubnetId().getValue()); + continue; } + // router Port have either IPv4 or IPv6, never both + ipVersion = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()); String ipValue = portIP.getIpAddress().stringValue(); neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, confTx); // NOTE: Please donot change the order of calls to removeSubnetFromVpn and // and updateSubnetNodeWithFixedIP - nvpnManager.removeSubnetFromVpn(vpnId, portIP.getSubnetId(), - sn != null ? sn.getInternetVpnId() : null); + nvpnManager.removeSubnetFromVpn(vpnId, sn, sn.getInternetVpnId()); nvpnManager.updateSubnetNodeWithFixedIp(portIP.getSubnetId(), null, null, null, null, null); } @@ -413,20 +441,21 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId); for (Subnetmap sn : snList) { if (sn.getNetworkId() == networkId) { @@ -445,7 +477,15 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

routersId = NeutronvpnUtils.buildExtRoutersIdentifier(routerId); - Optional optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId); - if (!optionalRouter.isPresent()) { - return; - } + Optional optionalRouter = null; + try { + optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId); + if (!optionalRouter.isPresent()) { + return; + } + Routers extRouters = optionalRouter.get(); + if (extRouters.getExtGwMacAddress() != null) { + return; + } - Routers extRouters = optionalRouter.get(); - if (extRouters.getExtGwMacAddress() != null) { - return; + RoutersBuilder builder = new RoutersBuilder(extRouters); + builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue()); + MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build()); + } catch (ExecutionException | InterruptedException e) { + LOG.error("setExternalGwMac: failed to read EXT-Routers for router Id {} rout-Gw port {} due to exception", + routerId, routerGwPort, e); } - RoutersBuilder builder = new RoutersBuilder(extRouters); - builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue()); - MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build()); } + @Nullable private String getPortHostId(final Port port) { if (port != null) { PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class); @@ -506,6 +553,7 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

unmarshal(final String profile) { if (null == profile) { return null; } Gson gson = new Gson(); JsonObject jsonObject = gson.fromJson(profile, JsonObject.class); - Map map = new HashMap(); + Map map = new HashMap<>(); for (Map.Entry entry : jsonObject.entrySet()) { map.put(entry.getKey(), entry.getValue()); } @@ -588,23 +637,26 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

portIpAddrsList = port.getFixedIps(); + final String networkId = port.getNetworkId().getValue(); + final List portIpAddrsList = port.nonnullFixedIps(); if (NeutronConstants.IS_ODL_DHCP_PORT.test(port)) { return; } - jobCoordinator.enqueueJob("PORT- " + portName, () -> { - // add direct port to subnetMaps config DS - if (!(NeutronUtils.isPortVnicTypeNormal(port) + if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port) && isSupportedVnicTypeByHost(port, NeutronConstants.VNIC_TYPE_DIRECT))) { - for (FixedIps ip: portIpAddrsList) { - nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId); - } - LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;" - + "OF Port interfaces are not created", portName); - return Collections.emptyList(); + for (FixedIps ip: portIpAddrsList) { + nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId); } - return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { + LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;" + + "OF Port interfaces are not created", portName); + return; + } + jobCoordinator.enqueueJob("PORT- " + portName, () -> { + // add direct port to subnetMaps config DS + // TODO: for direct port as well, operations should be carried out per subnet based on port IP + + ListenableFuture future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { LOG.info("Of-port-interface creation for port {}", portName); // Create of-port interface for this neutron port String portInterfaceName = createOfPortInterface(port, tx); @@ -634,33 +686,36 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

portIpsList = port.getFixedIps(); - jobCoordinator.enqueueJob("PORT- " + portName, - () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> { - if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) { - for (FixedIps ip : portIpsList) { - // remove direct port from subnetMaps config DS - nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId); - } - LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;" - + "Skipping OF Port interfaces removal", portName); - return; - } + final List portIpsList = port.nonnullFixedIps(); + if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) { + for (FixedIps ip : portIpsList) { + // remove direct port from subnetMaps config DS + // TODO: for direct port as well, operations should be carried out per subnet based on port IP + nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId); + } + LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;" + + "Skipping OF Port interfaces removal", portName); + return; + } + jobCoordinator.enqueueJob("PORT- " + portName, () -> { + ListenableFuture future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> { + Uuid vpnId = null; Set routerIds = new HashSet<>(); Uuid internetVpnId = null; @@ -707,7 +762,12 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

()); interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>()); + interfaceAclBuilder.setSubnetInfo(new ArrayList<>()); } } else { if (updatedSecurityEnabled) { @@ -825,7 +886,7 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase