fixes for several logical bugs 78/39478/6
authorMatej Perina <matej.perina@pantheon.sk>
Fri, 27 May 2016 11:26:54 +0000 (13:26 +0200)
committerMartin Sunal <msunal@cisco.com>
Sat, 28 May 2016 10:49:48 +0000 (10:49 +0000)
Fixes concurent transactions in NeLocationProvider, NullPointerException
in RendererUtils, registration of ForwardingResolver
and logical bugs in RendererManager

Change-Id: I9a09caafcf18fb309a682cd33de9a9fd09b95390
Signed-off-by: Matej Perina <matej.perina@pantheon.sk>
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/location/resolver/LocationResolver.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererManager.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/resolver/ForwardingResolver.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/NetUtils.java
location-providers/ne-location-provider/src/main/java/org/opendaylight/groupbasedpolicy/ne/location/provider/NeLocationProvider.java

index dfbf4d0678238af6ec101c9afc6b74e18a300585..e4b00dc8b14b245b3a6476ff227685e9fe939d60 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationBuilder;
@@ -87,7 +88,8 @@ public class LocationResolver implements DataTreeChangeListener<LocationProvider
                     break;
                 }
             }
-            wtx.submit();
+            LOG.debug("Writing endpoint location changes to DS");
+            DataStoreHelper.submitToDs(wtx);
         }
     }
 
index 16b68886cf0c4bd655c39bbae6c313126a82831f..15116792ce94aefe811b9bc3c65fa1bd4b24c2a0 100644 (file)
@@ -91,6 +91,8 @@ public class RendererManager implements AutoCloseable {
     private EndpointInfo epInfo;
     private EndpointLocationInfo epLocInfo;
     private Forwarding forwarding;
+    private boolean changesWaitingToProcess = false;
+    private boolean currentVersionHasConfig = false;
 
     private final EndpointsListener endpointsListener;
     private final EndpointLocationsListener endpointLocationsListener;
@@ -110,21 +112,25 @@ public class RendererManager implements AutoCloseable {
 
     public synchronized void endpointsUpdated(final Endpoints endpoints) {
         epInfo = new EndpointInfo(endpoints);
+        changesWaitingToProcess = true;
         processState();
     }
 
     public synchronized void endpointLocationsUpdated(final EndpointLocations epLocations) {
         epLocInfo = new EndpointLocationInfo(epLocations);
+        changesWaitingToProcess = true;
         processState();
     }
 
     public synchronized void resolvedPoliciesUpdated(final ResolvedPolicies resolvedPolicies) {
         policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
+        changesWaitingToProcess = true;
         processState();
     }
 
     public synchronized void forwardingUpdated(final Forwarding forwarding) {
         this.forwarding = forwarding;
+        changesWaitingToProcess = true;
         processState();
     }
 
@@ -138,7 +144,7 @@ public class RendererManager implements AutoCloseable {
             rendererByNode.put(nodePath, renderers.asList().get(0));
         }
         if (processingRenderers.isEmpty()) {
-            processState();
+            changesWaitingToProcess = true;
         } else {
             LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
                     processingRenderers);
@@ -161,6 +167,7 @@ public class RendererManager implements AutoCloseable {
                 }
             }
         }
+        processState();
     }
 
     private void processState() {
@@ -172,44 +179,66 @@ public class RendererManager implements AutoCloseable {
         if (rendererByNode.values().isEmpty()) {
             return;
         }
-
-        version++;
+        if (!changesWaitingToProcess) {
+            return;
+        }
         Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = createRendererConfigBuilders();
-        List<Renderer> renderers = new ArrayList<>();
         Set<RendererName> rendererNames = new HashSet<>(rendererByNode.values());
+        boolean newVersionHasConfig = false;
+        Map<RendererName, Optional<Configuration>> configsByRendererName = new HashMap<>();
         for (RendererName rendererName : rendererNames) {
             RendererConfigurationBuilder rendererPolicyBuilder = rendererConfigBuilderByRendererName.get(rendererName);
             Optional<Configuration> potentialConfig = createConfiguration(rendererPolicyBuilder);
-            RendererPolicy rendererPolicy = null;
             if (potentialConfig.isPresent()) {
-                LOG.debug("Created configuration for renderer with version {}", rendererName.getValue(), version);
-                rendererPolicy =
-                        new RendererPolicyBuilder().setVersion(version).setConfiguration(potentialConfig.get()).build();
+                newVersionHasConfig = true;
+            }
+            configsByRendererName.put(rendererName, potentialConfig);
+        }
+        if (newVersionHasConfig || currentVersionHasConfig) {
+            version++;
+            if (!writeRenderersConfigs(configsByRendererName)) {
+                LOG.warn("Version {} was not dispatched successfully. Previous version is valid until next update.",
+                        version);
+                for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
+                    processingRenderers.remove(rendererName);
+                }
+                version--;
+                changesWaitingToProcess = true;
+                return;
+            } else {
+                currentVersionHasConfig = newVersionHasConfig;
+            }
+        }
+        changesWaitingToProcess = false;
+    }
+
+    private boolean writeRenderersConfigs(Map<RendererName, Optional<Configuration>> configsByRendererName) {
+        List<Renderer> renderers = new ArrayList<>();
+        for (RendererName rendererName : configsByRendererName.keySet()) {
+            RendererPolicy rendererPolicy = null;
+            if (configsByRendererName.get(rendererName).isPresent()) {
+                rendererPolicy = new RendererPolicyBuilder().setVersion(version)
+                    .setConfiguration(configsByRendererName.get(rendererName).get())
+                    .build();
+
             } else {
-                rendererPolicy =
-                        new RendererPolicyBuilder().setVersion(version).build();
+                rendererPolicy = new RendererPolicyBuilder().setVersion(version).build();
             }
             renderers.add(new RendererBuilder().setName(rendererName).setRendererPolicy(rendererPolicy).build());
             processingRenderers.add(rendererName);
+            LOG.debug("Created configuration for renderer {} with version {}", rendererName.getValue(), version);
         }
         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
         wTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Renderers.class),
                 new RenderersBuilder().setRenderer(renderers).build());
-        if (!DataStoreHelper.submitToDs(wTx)) {
-            LOG.warn("Version {} was not dispatched successfully. Previous version is valid till next update.",
-                    version);
-            for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
-                processingRenderers.remove(rendererName);
-            }
-            version--;
-        }
+        return DataStoreHelper.submitToDs(wTx);
     }
 
     /**
      * Entry is added to the result map only if:<br>
      * 1. There is at least one Address EP with absolute location
      * 2. There is a renderer responsible for that EP
-     * 
+     *
      * @return
      */
     private Map<RendererName, RendererConfigurationBuilder> createRendererConfigBuilders() {
@@ -355,6 +384,9 @@ public class RendererManager implements AutoCloseable {
             return;
         }
         for (AddressEndpointKey peerAdrEpKey : peerAdrEps) {
+            if (isSameKeys(rendererEpKey, peerAdrEpKey)) {
+                continue;
+            }
             ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
             if (eig != null) {
                 if (!epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
@@ -399,6 +431,16 @@ public class RendererManager implements AutoCloseable {
         return false;
     }
 
+    private boolean isSameKeys(RendererEndpointKey rendererEpKey, AddressEndpointKey peerAdrEpKey) {
+        if (rendererEpKey.getAddress().equals(peerAdrEpKey.getAddress())
+                && rendererEpKey.getAddressType().equals(peerAdrEpKey.getAddressType())
+                && rendererEpKey.getContextId().equals(peerAdrEpKey.getContextId())
+                && rendererEpKey.getContextType().equals(peerAdrEpKey.getContextType())) {
+            return true;
+        }
+        return false;
+    }
+
     private Set<EpgKeyDto> toEpgKeys(List<EndpointGroupId> epgIds, TenantId tenantId) {
         return FluentIterable.from(epgIds).transform(new Function<EndpointGroupId, EpgKeyDto>() {
 
index 08cec8c6e8f14bdb208f6c229a34f6db907a7410..fc24581ed421cb70ad953f7aadcdfcd52899c298 100644 (file)
@@ -32,6 +32,9 @@ public class RendererUtils {
         }
         Builder<InstanceIdentifier<?>, RendererName> renderersByNodeBuilder = ImmutableMultimap.builder();
         for (Renderer renderer : renderers) {
+            if (renderer.getRendererNodes() == null) {
+                continue;
+            }
             List<RendererNode> rendererNodes = renderer.getRendererNodes().getRendererNode();
             if (rendererNodes == null) {
                 continue;
index 4d8877efa9b0de2d4f915e57e01b73e60e050891..08ae9bcce078f0f99956e61fa08e04d01e1c508a 100644 (file)
@@ -10,9 +10,11 @@ package org.opendaylight.groupbasedpolicy.resolver;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -23,6 +25,8 @@ public class ForwardingResolver extends DataTreeChangeHandler<ForwardingByTenant
 
     public ForwardingResolver(DataBroker dataProvider) {
         super(dataProvider);
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.builder(Forwarding.class).child(ForwardingByTenant.class).build()));
     }
 
     @Override
index a650f11fbb1a8a66ba203f93effafe43c3875ead..36152ac498dd7cdbb58e66718a614ca3b062ac7b 100644 (file)
@@ -99,8 +99,8 @@ public final class NetUtils {
         if (prefix1.getIpv4Prefix() != null && prefix2.getIpv4Prefix() != null) {
             SubnetUtils fromPrefix1 = new SubnetUtils(prefix1.getIpv4Prefix().getValue());
             SubnetUtils fromPrefix2 = new SubnetUtils(prefix2.getIpv4Prefix().getValue());
-            if (fromPrefix1.getInfo().isInRange(fromPrefix2.getInfo().getHighAddress())
-                    && fromPrefix2.getInfo().isInRange(fromPrefix1.getInfo().getHighAddress())) {
+            if (fromPrefix1.getInfo().getNetworkAddress().equals(fromPrefix2.getInfo().getNetworkAddress())
+                    && fromPrefix1.getInfo().getNetmask().equals(fromPrefix2.getInfo().getNetmask())) {
                 return true;
             }
         } else if (prefix1.getIpv6Prefix() != null && prefix2.getIpv6Prefix() != null) {
index e20046df8dca04e571fe7e3858c088fecc3719dd..97153e2766bc02535179f55e8cd39835c129c30c 100644 (file)
@@ -22,13 +22,14 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.NetUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.InternalLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElements;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElementsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElement;
@@ -73,11 +74,12 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     public synchronized void onEndpointsChange(Collection<DataTreeModification<AddressEndpoint>> changes) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         for (DataTreeModification<AddressEndpoint> change : changes) {
             switch (change.getRootNode().getModificationType()) {
                 case DELETE: {
                     AddressEndpoint endpoint = change.getRootNode().getDataBefore();
-                    removeLocationForEndpoint(endpoint);
+                    removeLocationForEndpoint(endpoint, wtx);
                     this.endpoints.remove(endpoint);
                     break;
                 }
@@ -89,7 +91,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                         break;
                     }
                     endpoint = change.getRootNode().getDataAfter();
-                    createLocationForEndpoint(endpoint);
+                    createLocationForEndpoint(endpoint, wtx);
                     this.endpoints.add(endpoint);
                     break;
                 }
@@ -100,9 +102,10 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 }
             }
         }
+        DataStoreHelper.submitToDs(wtx);
     }
 
-    private void createLocationForEndpoint(AddressEndpoint endpoint) {
+    private void createLocationForEndpoint(AddressEndpoint endpoint, WriteTransaction wtx) {
         for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
             for (Interface iface : nullToEmpty(ne.getInterface())) {
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
@@ -110,14 +113,12 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                             && endpoint.getContextId().equals(en.getL3ContextId())
                             && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
                                 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
-                        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
                         InstanceIdentifier<AbsoluteLocation> iid = IidFactory
                             .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
                                     endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                             .child(AbsoluteLocation.class);
                         wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(ne.getIid(), iface.getIid()),
                                 true);
-                        wtx.submit();
                         LOG.debug("New location created for endpoint {}", endpoint);
                         return;
                     }
@@ -126,7 +127,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
         }
     }
 
-    private void removeLocationForEndpoint(AddressEndpoint endpoint) {
+    private void removeLocationForEndpoint(AddressEndpoint endpoint, WriteTransaction wtx) {
         for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
             for (Interface iface : nullToEmpty(ne.getInterface())) {
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
@@ -134,13 +135,11 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                             && endpoint.getContextId().equals(en.getL3ContextId())
                             && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
                                 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
-                        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
                         InstanceIdentifier<AbsoluteLocation> iid = IidFactory
                             .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
                                     endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                             .child(AbsoluteLocation.class);
                         wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
-                        wtx.submit();
                         LOG.debug("Location deleted for endpoint {}", endpoint);
                         return;
                     }
@@ -151,6 +150,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
 
     @Override
     public synchronized void onDataTreeChanged(Collection<DataTreeModification<NetworkElements>> changes) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         for (DataTreeModification<NetworkElements> change : changes) {
             switch (change.getRootNode().getModificationType()) {
                 case DELETE: {
@@ -158,7 +158,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
                         for (Interface iface : nullToEmpty(ne.getInterface())) {
                             for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                                processDeletedEN(en);
+                                processDeletedEN(en, wtx);
                             }
                         }
                     }
@@ -172,7 +172,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                         for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
                             for (Interface iface : nullToEmpty(ne.getInterface())) {
                                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                                    processDeletedEN(en);
+                                    processDeletedEN(en, wtx);
                                 }
                             }
                         }
@@ -181,7 +181,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
                         for (Interface iface : nullToEmpty(ne.getInterface())) {
                             for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                                processCreatedEN(en, ne.getIid(), iface.getIid());
+                                processCreatedEN(en, ne.getIid(), iface.getIid(), wtx);
                             }
                         }
                     }
@@ -193,12 +193,13 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                     List<DataObjectModification<NetworkElement>> modifiedNetworkElements =
                             getModifiedNetworkElements(change.getRootNode());
                     for (DataObjectModification<NetworkElement> netElement : modifiedNetworkElements) {
-                        processNetworkElementChange(netElement);
+                        processNetworkElementChange(netElement, wtx);
                     }
                     break;
                 }
             }
         }
+        DataStoreHelper.submitToDs(wtx);
     }
 
     private List<DataObjectModification<NetworkElement>> getModifiedNetworkElements(
@@ -217,13 +218,13 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
         return nes;
     }
 
-    private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement) {
+    private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement, WriteTransaction wtx) {
         switch (netElement.getModificationType()) {
             case DELETE: {
                 NetworkElement ne = netElement.getDataBefore();
                 for (Interface iface : nullToEmpty(ne.getInterface())) {
                     for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                        processDeletedEN(en);
+                        processDeletedEN(en, wtx);
                     }
                 }
                 networkElements.getNetworkElement().remove(ne);
@@ -235,7 +236,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 if (ne != null) {
                     for (Interface iface : nullToEmpty(ne.getInterface())) {
                         for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                            processDeletedEN(en);
+                            processDeletedEN(en, wtx);
                         }
                     }
                     networkElements.getNetworkElement().remove(ne);
@@ -243,7 +244,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 ne = netElement.getDataAfter();
                 for (Interface iface : nullToEmpty(ne.getInterface())) {
                     for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                        processCreatedEN(en, ne.getIid(), iface.getIid());
+                        processCreatedEN(en, ne.getIid(), iface.getIid(), wtx);
                     }
                 }
                 networkElements.getNetworkElement().add(ne);
@@ -253,7 +254,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
             case SUBTREE_MODIFIED: {
                 List<DataObjectModification<Interface>> modifiedInterfaces = getModifiedInterfaces(netElement);
                 for (DataObjectModification<Interface> modifiedInterface : modifiedInterfaces) {
-                    processInterfaceChange(modifiedInterface, netElement.getDataBefore());
+                    processInterfaceChange(modifiedInterface, netElement.getDataBefore(), wtx);
                 }
                 break;
             }
@@ -277,12 +278,12 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     private void processInterfaceChange(DataObjectModification<Interface> modifiedInterface,
-            NetworkElement nodeBefore) {
+            NetworkElement nodeBefore, WriteTransaction wtx) {
         switch (modifiedInterface.getModificationType()) {
             case DELETE: {
                 Interface iface = modifiedInterface.getDataBefore();
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                    processDeletedEN(en);
+                    processDeletedEN(en, wtx);
                 }
                 int nodeIndex = getIndexOf(nodeBefore);
                 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
@@ -294,13 +295,13 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 int nodeIndex = getIndexOf(nodeBefore);
                 if (iface != null) {
                     for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                        processDeletedEN(en);
+                        processDeletedEN(en, wtx);
                     }
                     networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
                 }
                 iface = modifiedInterface.getDataAfter();
                 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
-                    processCreatedEN(en, nodeBefore.getIid(), iface.getIid());
+                    processCreatedEN(en, nodeBefore.getIid(), iface.getIid(), wtx);
                 }
                 networkElements.getNetworkElement().get(nodeIndex).getInterface().add(iface);
                 LOG.debug("Created new Interface {}", modifiedInterface.getDataAfter());
@@ -310,7 +311,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 List<DataObjectModification<EndpointNetwork>> modifiedENs =
                         getModifiedEndpointNetworks(modifiedInterface);
                 for (DataObjectModification<EndpointNetwork> modifiedEN : modifiedENs) {
-                    processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore());
+                    processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore(), wtx);
                 }
                 break;
             }
@@ -334,10 +335,10 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     private void processEndpointNetworkChange(DataObjectModification<EndpointNetwork> modifiedEN,
-            NetworkElement nodeBefore, Interface ifaceBefore) {
+            NetworkElement nodeBefore, Interface ifaceBefore, WriteTransaction wtx) {
         switch (modifiedEN.getModificationType()) {
             case DELETE: {
-                processDeletedEN(modifiedEN.getDataBefore());
+                processDeletedEN(modifiedEN.getDataBefore(), wtx);
                 int nodeIndex = getIndexOf(nodeBefore);
                 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
                 networkElements.getNetworkElement()
@@ -350,7 +351,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                 break;
             }
             case WRITE: {
-                processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid());
+                processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid(), wtx);
                 int nodeIndex = getIndexOf(nodeBefore);
                 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
                 networkElements.getNetworkElement()
@@ -370,8 +371,7 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
     }
 
     private void processCreatedEN(EndpointNetwork en, InstanceIdentifier<?> nodeIID,
-            InstanceIdentifier<?> connectorIID) {
-        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+            InstanceIdentifier<?> connectorIID, WriteTransaction wtx) {
         for (AddressEndpoint endpoint : endpoints) {
             if (endpoint.getContextType().isAssignableFrom(L3Context.class)
                     && endpoint.getContextId().equals(en.getL3ContextId())
@@ -382,15 +382,13 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                             endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                     .child(AbsoluteLocation.class);
                 wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(nodeIID, connectorIID), true);
-                wtx.submit();
                 LOG.debug("New location created for endpoint {}", endpoint);
                 return;
             }
         }
     }
 
-    private void processDeletedEN(EndpointNetwork en) {
-        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+    private void processDeletedEN(EndpointNetwork en, WriteTransaction wtx) {
         for (AddressEndpoint endpoint : endpoints) {
             if (endpoint.getContextType().isAssignableFrom(L3Context.class)
                     && endpoint.getContextId().equals(en.getL3ContextId())
@@ -401,7 +399,6 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
                             endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
                     .child(AbsoluteLocation.class);
                 wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
-                wtx.submit();
                 LOG.debug("Location deleted for endpoint {}", endpoint);
                 return;
             }
@@ -410,7 +407,8 @@ public class NeLocationProvider implements DataTreeChangeListener<NetworkElement
 
     private AbsoluteLocation createRealLocation(InstanceIdentifier<?> node, InstanceIdentifier<?> iface) {
         return new AbsoluteLocationBuilder()
-            .setLocationType(new InternalLocationCaseBuilder().setInternalNode(node).setInternalNodeConnector(iface).build()).build();
+            .setLocationType(new ExternalLocationCaseBuilder().setExternalNodeMountPoint(node)
+                    .setExternalNodeConnector(iface.toString()).build()).build();
     }
 
     private <T> List<T> nullToEmpty(@Nullable List<T> list) {