Bug 8559 - updating metadata endpoints 45/58245/6
authorTomas Cechvala <tcechval@cisco.com>
Mon, 5 Jun 2017 13:15:09 +0000 (15:15 +0200)
committerTomas Cechvala <tcechval@cisco.com>
Mon, 5 Jun 2017 16:11:16 +0000 (16:11 +0000)
When router interface attaches to a subnet, metadata
endpoints have not been updated.

Change-Id: I34064a0ab5e77204c4c7568ef5e3efaa69970faa
Signed-off-by: Tomas Cechvala <tcechval@cisco.com>
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/PortUtils.java

index b80b9f6f1b1ddcfbb0cd369889a376743f78faf9..af5448af95877b295adf6c039c609ea20a595399 100644 (file)
@@ -13,6 +13,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
 import javax.annotation.Nullable;
@@ -211,20 +212,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
             registerBaseEndpointAndStoreMapping(
                     ImmutableList.of(l3BaseEp.build(), l2BaseEp.build()), port, rwTx, addBaseEpMapping);
-
-            AddressEndpointRegBuilder metadataEp = createBasicL3AddrEpInputBuilder(cloneMetadataPortFromDhcpPort(port, metadataIpPrefix), networkContainment,
-                    Lists.newArrayList(MetadataService.EPG_ID), neutron);
-            AddressEndpointKey aek = new AddressEndpointKey(metadataEp.getAddress(), metadataEp.getAddressType(), metadataEp.getContextId(), metadataEp.getContextType());
-            Optional<AddressEndpoint> optMetadataEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek), rwTx);
-            if(!optMetadataEp.isPresent()) {
-                setParentChildRelationshipForEndpoints(metadataEp, l2BaseEp);
-            } else {
-                List<ChildEndpoint> childs = optMetadataEp.get().getChildEndpoint();
-                childs.add(createChildEndpoint(l2BaseEp));
-                metadataEp.setChildEndpoint(childs);
-            }
-            registerBaseEndpointAndStoreMapping(
-                    ImmutableList.of(metadataEp.build()), port, rwTx, true);
+            registerMetadataServiceForDhcpPort(port, neutron, l2BaseEp, rwTx, true);
             registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
             DataStoreHelper.submitToDs(rwTx);
         } else if (PortUtils.isNormalPort(port)) {
@@ -278,6 +266,30 @@ public class NeutronPortAware implements NeutronAware<Port> {
         return new PortBuilder(port).setFixedIps(metadataIps).build();
     }
 
+    private void registerMetadataServiceForDhcpPort(Port port, Neutron neutron, AddressEndpointRegBuilder childEpToAdd,
+            ReadWriteTransaction rwTx, boolean registerMapping) {
+        Optional<NetworkDomainId> resolveNetworkContainment = PortUtils.resolveNetworkContainment(port);
+        if (!resolveNetworkContainment.isPresent()) {
+            LOG.warn("DHCP port does not have an IP address. {}", port);
+            return;
+        }
+        AddressEndpointRegBuilder metadataEp =
+                createBasicL3AddrEpInputBuilder(cloneMetadataPortFromDhcpPort(port, metadataIpPrefix),
+                        resolveNetworkContainment.get(), Lists.newArrayList(MetadataService.EPG_ID), neutron);
+        AddressEndpointKey aek = new AddressEndpointKey(metadataEp.getAddress(), metadataEp.getAddressType(),
+                metadataEp.getContextId(), metadataEp.getContextType());
+        Optional<AddressEndpoint> optMetadataEp =
+                DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek), rwTx);
+        if (!optMetadataEp.isPresent()) {
+            setParentChildRelationshipForEndpoints(metadataEp, childEpToAdd);
+        } else {
+            List<ChildEndpoint> childs = optMetadataEp.get().getChildEndpoint();
+            childs.add(createChildEndpoint(childEpToAdd));
+            metadataEp.setChildEndpoint(childs);
+        }
+        registerBaseEndpointAndStoreMapping(ImmutableList.of(metadataEp.build()), port, rwTx, registerMapping);
+    }
+
     private void setParentChildRelationshipForEndpoints(AddressEndpointRegBuilder parentEp,
             AddressEndpointRegBuilder childEp) {
         childEp.setParentEndpointChoice(new ParentEndpointCaseBuilder().setParentEndpoint(
@@ -320,6 +332,22 @@ public class NeutronPortAware implements NeutronAware<Port> {
             LOG.debug("No new data are written, there is no L3 context in subnet {} to update", subnetUuid);
             return;
         }
+        java.util.Optional<Subnet> optSubnet = neutron.getSubnets()
+            .getSubnet()
+            .stream()
+            .filter(subnet -> subnet.getNetworkId() != null && subnet.getUuid().getValue().equals(subnetUuid.getValue()))
+            .findAny();
+        if (!optSubnet.isPresent()) {
+            LOG.error("Failed to update metadata endpoint in subnet {}. Could not resolve Network ID", subnetUuid);
+        } else {
+            AddressEndpointUnreg metadataEpUnreg =
+                    new AddressEndpointUnregBuilder().setAddress(String.valueOf(metadataIpPrefix.getValue()))
+                        .setAddressType(IpPrefixType.class)
+                        .setContextId(new ContextId(optSubnet.get().getNetworkId().getValue()))
+                        .setContextType(MappingUtils.L3_CONTEXT)
+                        .build();
+            epRegistrator.unregisterEndpoint(metadataEpUnreg);
+        }
         Set<Port> portsInSameSubnet = PortUtils.findPortsBySubnet(subnetUuid, neutron.getPorts());
         for (Port portInSameSubnet : portsInSameSubnet) {
             if (PortUtils.isNormalPort(portInSameSubnet) || PortUtils.isDhcpPort(portInSameSubnet)
@@ -350,7 +378,15 @@ public class NeutronPortAware implements NeutronAware<Port> {
                     RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder()
                         .setAddressEndpointReg(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build())).build();
                     epRegistrator.registerEndpoint(regBaseEpInput);
-
+                    if(PortUtils.isDhcpPort(portInSameSubnet)) {
+                        ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+                        registerMetadataServiceForDhcpPort(portInSameSubnet, neutron, l2BaseEp, rwTx, false);
+                        try {
+                            rwTx.submit().get();
+                        } catch (InterruptedException | ExecutionException e) {
+                            LOG.error("Failed to update metadata endpoint for DHCP port {}. {}", portInSameSubnet, e);
+                        }
+                    }
                     modifyL3ContextForEndpoints(portInSameSubnet, ipWithSubnet, l3BaseEp.getContextId());
                 }
             }
index 2e225876771f98de757c5a47ff9b2b75a4da8277..621f3b15daf65eaa5b0464deee5a38336ec23a7c 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Set;
 import javax.annotation.Nullable;
 
 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.groupbasedpolicy.common.rev140421.NetworkDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
 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.ports.attributes.Ports;
@@ -82,6 +83,15 @@ public class PortUtils {
         return Optional.absent();
     }
 
+    public static Optional<NetworkDomainId> resolveNetworkContainment(Port port) {
+        Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
+        if (firstFixedIps.isPresent() && firstFixedIps.get().getSubnetId() != null) {
+            FixedIps ipWithSubnet = firstFixedIps.get();
+            return Optional.of(new NetworkDomainId(ipWithSubnet.getSubnetId().getValue()));
+        }
+        return Optional.absent();
+    }
+
     public static boolean isNormalPort(Port port) {
         if (isDhcpPort(port) || isRouterInterfacePort(port) || isRouterGatewayPort(port) || isFloatingIpPort(port)) {
             return false;