Lower log levels for non error's
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnNatManager.java
index 942ddd48735bde8c007c0666ac0ad17befe70c7e..f0ac3a13503377985329248e84ba140f5f6d0c9b 100644 (file)
@@ -11,19 +11,33 @@ import com.google.common.base.Optional;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
 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.TransactionCommitFailedException;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
 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.netvirt.natservice.rev160111.ExternalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
 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.ext.routers.RoutersKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.ExternalGatewayInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.external_gateway_info.ExternalFixedIps;
@@ -33,6 +47,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Singleton
 public class NeutronvpnNatManager implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnNatManager.class);
     private final DataBroker dataBroker;
@@ -41,43 +56,48 @@ public class NeutronvpnNatManager implements AutoCloseable {
     private static final int EXTERNAL_REMOVED = 2;
     private static final int EXTERNAL_CHANGED = 3;
 
+    @Inject
     public NeutronvpnNatManager(final DataBroker dataBroker) {
         this.dataBroker = dataBroker;
     }
 
     @Override
+    @PreDestroy
     public void close() throws Exception {
         LOG.info("{} close", getClass().getSimpleName());
     }
 
     public void handleExternalNetworkForRouter(Router original, Router update) {
-
         Uuid routerId = update.getUuid();
         Uuid origExtNetId = null;
         Uuid updExtNetId = null;
+        List<ExternalFixedIps> origExtFixedIps;
 
-        LOG.trace("handleExternalNetwork for router " +  routerId);
+        LOG.trace("handleExternalNetwork for router {}", routerId);
         int extNetChanged = externalNetworkChanged(original, update);
         if (extNetChanged != EXTERNAL_NO_CHANGE) {
             if (extNetChanged == EXTERNAL_ADDED) {
                 updExtNetId = update.getExternalGatewayInfo().getExternalNetworkId();
-                LOG.trace("External Network " + updExtNetId.getValue()
-                    + " addition detected for router " +  routerId.getValue());
+                LOG.trace("External Network {} addition detected for router", updExtNetId.getValue(),
+                        routerId.getValue());
                 addExternalNetworkToRouter(update);
                 return;
             }
             if (extNetChanged == EXTERNAL_REMOVED) {
                 origExtNetId = original.getExternalGatewayInfo().getExternalNetworkId();
+                origExtFixedIps = original.getExternalGatewayInfo().getExternalFixedIps();
                 LOG.trace("External Network removal detected for router {}", routerId.getValue());
-                removeExternalNetworkFromRouter(origExtNetId, update);
+                removeExternalNetworkFromRouter(origExtNetId, update, origExtFixedIps);
                 //gateway mac unset handled as part of gateway clear deleting top-level routers node
                 return;
             }
+
             origExtNetId = original.getExternalGatewayInfo().getExternalNetworkId();
+            origExtFixedIps = original.getExternalGatewayInfo().getExternalFixedIps();
             updExtNetId = update.getExternalGatewayInfo().getExternalNetworkId();
             LOG.trace("External Network changed from {} to {} for router {}",
                 origExtNetId.getValue(), updExtNetId.getValue(), routerId.getValue());
-            removeExternalNetworkFromRouter(origExtNetId, update);
+            removeExternalNetworkFromRouter(origExtNetId, update, origExtFixedIps);
             addExternalNetworkToRouter(update);
             return;
         }
@@ -200,17 +220,17 @@ public class NeutronvpnNatManager implements AutoCloseable {
             .child(Networks.class, new NetworksKey(extNetId)).build();
 
         try {
-            LOG.trace(" Creating/Updating a new Networks node: " +  extNetId.getValue());
-            Optional<Networks> optionalNets = NeutronvpnUtils.read(dataBroker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    netsIdentifier);
+            LOG.trace(" Creating/Updating a new Networks node {}", extNetId.getValue());
+            Optional<Networks> optionalNets =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            netsIdentifier);
             if (optionalNets.isPresent()) {
                 LOG.error("External Network {} already detected to be present", extNetId.getValue());
                 return;
             }
             ProviderTypes provType = NeutronvpnUtils.getProviderNetworkType(net);
             if (provType == null) {
-                LOG.error("Unable to get Network Provider Type for network {}", net.getUuid());
+                LOG.error("Unable to get Network Provider Type for network {}", extNetId);
                 return;
             }
             NetworksBuilder builder = null;
@@ -221,11 +241,11 @@ public class NeutronvpnNatManager implements AutoCloseable {
 
             Networks networkss = builder.build();
             // Add Networks object to the ExternalNetworks list
-            LOG.trace("Creating externalnetworks " + networkss);
+            LOG.trace("Creating externalnetworks {}", networkss);
             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier, networkss);
             LOG.trace("Wrote externalnetwork successfully to CONFIG Datastore");
         } catch (Exception ex) {
-            LOG.error("Creation of External Network {} failed: {}", extNetId.getValue(), ex.getMessage());
+            LOG.error("Creation of External Network {} failed", extNetId.getValue(), ex);
         }
     }
 
@@ -239,21 +259,21 @@ public class NeutronvpnNatManager implements AutoCloseable {
             .child(Networks.class, new NetworksKey(extNetId)).build();
 
         try {
-            Optional<Networks> optionalNets = NeutronvpnUtils.read(dataBroker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    netsIdentifier);
-            LOG.trace("Removing Networks node: " +  extNetId.getValue());
+            Optional<Networks> optionalNets =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            netsIdentifier);
+            LOG.trace("Removing Networks node {}", extNetId.getValue());
             if (!optionalNets.isPresent()) {
-                LOG.info("External Network {} not available in the datastore", extNetId.getValue());
+                LOG.error("External Network {} not available in the datastore", extNetId.getValue());
                 return;
             }
             // Delete Networks object from the ExternalNetworks list
-            LOG.trace("Deleting External Network " + extNetId.getValue());
+            LOG.trace("Deleting External Network {}", extNetId.getValue());
             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier);
             LOG.trace("Deleted External Network {} successfully from CONFIG Datastore", extNetId.getValue());
 
         } catch (Exception ex) {
-            LOG.error("Deletion of External Network {} failed: {}", extNetId.getValue(), ex.getMessage());
+            LOG.error("Deletion of External Network {} failed", extNetId.getValue(), ex);
         }
     }
 
@@ -262,69 +282,74 @@ public class NeutronvpnNatManager implements AutoCloseable {
     private void addExternalNetworkToRouter(Router update) {
         Uuid routerId = update.getUuid();
         Uuid extNetId = update.getExternalGatewayInfo().getExternalNetworkId();
+        List<ExternalFixedIps> externalFixedIps = update.getExternalGatewayInfo().getExternalFixedIps();
 
         try {
             Network input = NeutronvpnUtils.getNeutronNetwork(dataBroker, extNetId);
             ProviderTypes providerNwType = NeutronvpnUtils.getProviderNetworkType(input);
             if (providerNwType == null) {
-                LOG.error("Unable to get Network Provider Type for network {} and uuid {}",
-                    input.getName(), input.getUuid());
+                LOG.error("Unable to get Network Provider Type for network {}", input.getUuid().getValue());
                 return;
             }
             // Add this router to the ExtRouters list
             addExternalRouter(update, dataBroker);
 
+            // Update External Subnets for this router
+            updateExternalSubnetsForRouter(routerId, extNetId, externalFixedIps);
+
             // Create and add Networks object for this External Network to the ExternalNetworks list
             InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
                 .child(Networks.class, new NetworksKey(extNetId)).build();
 
-            Optional<Networks> optionalNets = NeutronvpnUtils.read(dataBroker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    netsIdentifier);
-            NetworksBuilder builder = null;
-            if (optionalNets.isPresent()) {
-                builder = new NetworksBuilder(optionalNets.get());
-            } else {
+            Optional<Networks> optionalNets =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            netsIdentifier);
+            if (!optionalNets.isPresent()) {
                 LOG.error("External Network {} not present in the NVPN datamodel", extNetId.getValue());
                 return;
             }
+            NetworksBuilder builder = new NetworksBuilder(optionalNets.get());
             List<Uuid> rtrList = builder.getRouterIds();
             if (rtrList == null) {
                 rtrList = new ArrayList<>();
             }
             rtrList.add(routerId);
             builder.setRouterIds(rtrList);
-            if (providerNwType != ProviderTypes.GRE) {
+            if (NeutronvpnUtils.isFlatOrVlanNetwork(input)) {
                 builder.setVpnid(extNetId);
             }
 
             Networks networkss = builder.build();
             // Add Networks object to the ExternalNetworks list
-            LOG.trace("Updating externalnetworks " + networkss);
+            LOG.trace("Updating externalnetworks {}", networkss);
             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier, networkss);
             LOG.trace("Updated externalnetworks successfully to CONFIG Datastore");
         } catch (Exception ex) {
-            LOG.error("Creation of externalnetworks failed for {} with exception {}",
-                extNetId.getValue(), ex.getMessage());
+            LOG.error("Creation of externalnetworks failed for {}",
+                extNetId.getValue(), ex);
         }
     }
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    public void removeExternalNetworkFromRouter(Uuid origExtNetId, Router update) {
+    public void removeExternalNetworkFromRouter(Uuid origExtNetId, Router update,
+            List<ExternalFixedIps> origExtFixedIps) {
         Uuid routerId = update.getUuid();
 
         // Remove the router to the ExtRouters list
         removeExternalRouter(origExtNetId, update, dataBroker);
 
+        // Remove the router from External Subnets
+        removeRouterFromExternalSubnets(routerId, origExtNetId, origExtFixedIps);
+
         // Remove the router from the ExternalNetworks list
         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
             .child(Networks.class, new NetworksKey(origExtNetId)).build();
 
         try {
-            Optional<Networks> optionalNets = NeutronvpnUtils.read(dataBroker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    netsIdentifier);
+            Optional<Networks> optionalNets =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            netsIdentifier);
             LOG.trace("Removing a router from External Networks node: {}", origExtNetId.getValue());
             if (optionalNets.isPresent()) {
                 NetworksBuilder builder = new NetworksBuilder(optionalNets.get());
@@ -338,8 +363,8 @@ public class NeutronvpnNatManager implements AutoCloseable {
                 }
             }
         } catch (Exception ex) {
-            LOG.error("Removing externalnetwork {} from router {} failed {}",
-                origExtNetId.getValue(), routerId, ex.getMessage());
+            LOG.error("Removing externalnetwork {} from router {} failed", origExtNetId.getValue(),
+                    routerId.getValue(), ex);
         }
     }
 
@@ -353,9 +378,10 @@ public class NeutronvpnNatManager implements AutoCloseable {
             .child(Networks.class, new NetworksKey(extNetId)).build();
 
         try {
-            Optional<Networks> optionalNets = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                    netsIdentifier);
-            LOG.trace("Adding vpn-id into Networks node: " +  extNetId.getValue());
+            Optional<Networks> optionalNets =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            netsIdentifier);
+            LOG.trace("Adding vpn-id into Networks node {}", extNetId.getValue());
             NetworksBuilder builder = null;
             if (optionalNets.isPresent()) {
                 builder = new NetworksBuilder(optionalNets.get());
@@ -366,12 +392,12 @@ public class NeutronvpnNatManager implements AutoCloseable {
             builder.setVpnid(vpnId);
             Networks networkss = builder.build();
             // Add Networks object to the ExternalNetworks list
-            LOG.trace("Setting VPN-ID for externalnetworks " + networkss);
+            LOG.trace("Setting VPN-ID for externalnetworks {}", networkss);
             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier, networkss);
             LOG.trace("Wrote with VPN-ID successfully to CONFIG Datastore");
 
         } catch (Exception ex) {
-            LOG.error("Attaching VPN-ID to externalnetwork {} failed with {}", extNetId.getValue(), ex.getMessage());
+            LOG.error("Attaching VPN-ID to externalnetwork {} failed", extNetId.getValue(), ex);
         }
     }
 
@@ -385,26 +411,27 @@ public class NeutronvpnNatManager implements AutoCloseable {
             .child(Networks.class, new NetworksKey(extNetId)).build();
 
         try {
-            Optional<Networks> optionalNets = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                    netsIdentifier);
-            LOG.trace("Removing vpn-id from Networks node: " +  extNetId.getValue());
+            Optional<Networks> optionalNets =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            netsIdentifier);
+            LOG.trace("Removing vpn-id from Networks node {}", extNetId.getValue());
             NetworksBuilder builder = null;
             if (optionalNets.isPresent()) {
                 builder = new NetworksBuilder(optionalNets.get());
             } else {
-                LOG.error("External Network " + extNetId.getValue() + " not present in the NVPN datamodel");
+                LOG.error("External Network {} not present in the NVPN datamodel", extNetId.getValue());
                 return;
             }
 
             builder.setVpnid(null);
             Networks networkss = builder.build();
             // Add Networks object to the ExternalNetworks list
-            LOG.trace("Remove vpn-id for externalnetwork " + networkss);
+            LOG.trace("Remove vpn-id for externalnetwork {}", networkss);
             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier, networkss);
             LOG.trace("Updated extnetworks successfully to CONFIG Datastore");
 
         } catch (Exception ex) {
-            LOG.error("Removing VPN-ID from externalnetworks {} failed with {}", extNetId.getValue(), ex.getMessage());
+            LOG.error("Removing VPN-ID from externalnetworks {} failed", extNetId.getValue(), ex);
         }
     }
 
@@ -414,7 +441,6 @@ public class NeutronvpnNatManager implements AutoCloseable {
         Uuid routerId = update.getUuid();
         Uuid extNetId = update.getExternalGatewayInfo().getExternalNetworkId();
         Uuid gatewayPortId = update.getGatewayPortId();
-
         // Create and add Routers object for this Router to the ExtRouters list
 
         // Create a Routers object
@@ -424,14 +450,13 @@ public class NeutronvpnNatManager implements AutoCloseable {
             Network input = NeutronvpnUtils.getNeutronNetwork(dataBroker, extNetId);
             ProviderTypes providerNwType = NeutronvpnUtils.getProviderNetworkType(input);
             if (providerNwType == null) {
-                LOG.error("Unable to get Network Provider Type for network {} and uuid{}",
-                    input.getName(), input.getUuid());
+                LOG.error("Unable to get Network Provider Type for network {}", input.getUuid().getValue());
                 return;
             }
-            Optional<Routers> optionalRouters = NeutronvpnUtils.read(broker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    routersIdentifier);
-            LOG.trace("Creating/Updating a new Routers node: " + routerId.getValue());
+            Optional<Routers> optionalRouters =
+                    SingleTransactionDataBroker.syncReadOptional(broker, LogicalDatastoreType.CONFIGURATION,
+                            routersIdentifier);
+            LOG.trace("Creating/Updating a new Routers node: {}", routerId.getValue());
             RoutersBuilder builder = null;
             if (optionalRouters.isPresent()) {
                 builder = new RoutersBuilder(optionalRouters.get());
@@ -442,11 +467,11 @@ public class NeutronvpnNatManager implements AutoCloseable {
             builder.setNetworkId(extNetId);
             builder.setEnableSnat(update.getExternalGatewayInfo().isEnableSnat());
 
-            ArrayList<String> extFixedIps = new ArrayList<>();
+            ArrayList<ExternalIps> externalIps = new ArrayList<>();
             for (ExternalFixedIps fixedIps : update.getExternalGatewayInfo().getExternalFixedIps()) {
-                extFixedIps.add(fixedIps.getIpAddress().getIpv4Address().getValue());
+                addExternalFixedIpToExternalIpsList(externalIps, fixedIps);
             }
-            builder.setExternalIps(extFixedIps);
+            builder.setExternalIps(externalIps);
 
             if (gatewayPortId != null) {
                 LOG.trace("Setting/Updating gateway Mac for router {}", routerId.getValue());
@@ -459,13 +484,13 @@ public class NeutronvpnNatManager implements AutoCloseable {
             builder.setSubnetIds(subList);
             Routers routers = builder.build();
             // Add Routers object to the ExtRouters list
-            LOG.trace("Creating extrouters " + routers);
+            LOG.trace("Creating extrouters {}", routers);
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier, builder.build());
             LOG.trace("Wrote successfully Routers to CONFIG Datastore");
 
         } catch (Exception ex) {
-            LOG.error("Creation of extrouters failed for router {} failed with {}",
-                routerId.getValue(),  ex.getMessage());
+            LOG.error("Creation of extrouters failed for router {} failed",
+                routerId.getValue(), ex);
         }
     }
 
@@ -477,19 +502,19 @@ public class NeutronvpnNatManager implements AutoCloseable {
         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
 
         try {
-            Optional<Routers> optionalRouters = NeutronvpnUtils.read(broker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    routersIdentifier);
-            LOG.trace(" Removing Routers node: " +  routerId.getValue());
+            Optional<Routers> optionalRouters =
+                    SingleTransactionDataBroker.syncReadOptional(broker, LogicalDatastoreType.CONFIGURATION,
+                            routersIdentifier);
+            LOG.trace(" Removing Routers node {}", routerId.getValue());
             if (optionalRouters.isPresent()) {
                 RoutersBuilder builder = new RoutersBuilder(optionalRouters.get());
                 builder.setExternalIps(null);
                 builder.setSubnetIds(null);
                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier);
-                LOG.trace("Removed router " + routerId.getValue() + " from extrouters ");
+                LOG.trace("Removed router {} from extrouters", routerId.getValue());
             }
         } catch (Exception ex) {
-            LOG.error("Removing extrouter {} from extrouters failed with {}", routerId.getValue(), ex.getMessage());
+            LOG.error("Removing extrouter {} from extrouters failed", routerId.getValue(), ex);
         }
     }
 
@@ -497,30 +522,32 @@ public class NeutronvpnNatManager implements AutoCloseable {
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void handleExternalFixedIpsForRouter(Router update, DataBroker broker) {
         Uuid routerId = update.getUuid();
-
         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
-
         try {
-            Optional<Routers> optionalRouters = NeutronvpnUtils.read(broker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    routersIdentifier);
-            LOG.trace("Updating External Fixed IPs Routers node: " +  routerId.getValue());
+            Optional<Routers> optionalRouters =
+                    SingleTransactionDataBroker.syncReadOptional(broker, LogicalDatastoreType.CONFIGURATION,
+                            routersIdentifier);
+            LOG.trace("Updating External Fixed IPs Routers node {}", routerId.getValue());
             if (optionalRouters.isPresent()) {
                 RoutersBuilder builder = new RoutersBuilder(optionalRouters.get());
                 if (builder != null) {
-                    ArrayList<String> extFixedIps = new ArrayList<>();
+                    ArrayList<ExternalIps> externalIps = new ArrayList<>();
                     for (ExternalFixedIps fixedIps : update.getExternalGatewayInfo().getExternalFixedIps()) {
-                        extFixedIps.add(fixedIps.getIpAddress().getIpv4Address().getValue());
+                        addExternalFixedIpToExternalIpsList(externalIps, fixedIps);
                     }
-                    builder.setExternalIps(extFixedIps);
+
+                    builder.setExternalIps(externalIps);
                 }
+
+                updateExternalSubnetsForRouter(routerId, update.getExternalGatewayInfo().getExternalNetworkId(),
+                        update.getExternalGatewayInfo().getExternalFixedIps());
                 Routers routerss = builder.build();
                 LOG.trace("Updating external fixed ips for router {} with value {}", routerId.getValue(), routerss);
                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier, routerss);
                 LOG.trace("Added External Fixed IPs successfully for Routers to CONFIG Datastore");
             }
         } catch (Exception ex) {
-            LOG.error("Updating extfixedips for {} in extrouters failed with {}", routerId.getValue(), ex.getMessage());
+            LOG.error("Updating extfixedips for {} in extrouters failed", routerId.getValue(), ex);
         }
     }
 
@@ -530,28 +557,27 @@ public class NeutronvpnNatManager implements AutoCloseable {
         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
 
         try {
-            Optional<Routers> optionalRouters = NeutronvpnUtils.read(broker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    routersIdentifier);
+            Optional<Routers> optionalRouters =
+                    SingleTransactionDataBroker.syncReadOptional(broker, LogicalDatastoreType.CONFIGURATION,
+                            routersIdentifier);
             LOG.trace("Updating Internal subnets for Routers node: {}", routerId.getValue());
             RoutersBuilder builder = null;
             if (optionalRouters.isPresent()) {
                 builder = new RoutersBuilder(optionalRouters.get());
             } else {
-                LOG.info("No Routers element found for router name " + routerId.getValue());
+                LOG.debug("No Routers element found for router {}", routerId.getValue());
                 return;
             }
             List<Uuid> subList = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
             builder.setSubnetIds(subList);
             Routers routerss = builder.build();
             // Add Routers object to the ExtRouters list
-            LOG.trace("Updating extrouters " + routerss);
+            LOG.trace("Updating extrouters {}", routerss);
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier, routerss);
             LOG.trace("Updated successfully Routers to CONFIG Datastore");
-
         } catch (Exception ex) {
-            LOG.error("Updation of internal subnets for extrouters failed for router {} with {}",
-                routerId.getValue(), ex.getMessage());
+            LOG.error("Updation of internal subnets for extrouters failed for router {}",
+                routerId.getValue(), ex);
         }
     }
 
@@ -563,27 +589,173 @@ public class NeutronvpnNatManager implements AutoCloseable {
         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
 
         try {
-            Optional<Routers> optionalRouters = NeutronvpnUtils.read(broker,
-                    LogicalDatastoreType.CONFIGURATION,
-                    routersIdentifier);
+            Optional<Routers> optionalRouters =
+                    SingleTransactionDataBroker.syncReadOptional(broker, LogicalDatastoreType.CONFIGURATION,
+                            routersIdentifier);
             LOG.trace("Updating Internal subnets for Routers node: {}", routerId.getValue());
             RoutersBuilder builder = null;
             if (optionalRouters.isPresent()) {
                 builder = new RoutersBuilder(optionalRouters.get());
             } else {
-                LOG.trace("No Routers element found for router name " + routerId.getValue());
+                LOG.trace("No Routers element found for router name {}", routerId.getValue());
                 return;
             }
             builder.setEnableSnat(update.getExternalGatewayInfo().isEnableSnat());
             Routers routerss = builder.build();
             // Add Routers object to the ExtRouters list
-            LOG.trace("Updating extrouters for snat change " + routerss);
+            LOG.trace("Updating extrouters for snat change {}", routerss);
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier, routerss);
             LOG.trace("Updated successfully Routers to CONFIG Datastore");
 
         } catch (Exception ex) {
-            LOG.error("Updation of snat for extrouters failed for router {} with {}",
-                routerId.getValue(), ex.getMessage());
+            LOG.error("Updation of snat for extrouters failed for router {}", routerId.getValue(), ex);
+        }
+    }
+
+    public void updateOrAddExternalSubnet(Uuid networkId, Uuid subnetId, List<Uuid> routerIds) {
+        Optional<Subnets> optionalExternalSubnets = NeutronvpnUtils.getOptionalExternalSubnets(dataBroker, subnetId);
+        if (optionalExternalSubnets.isPresent()) {
+            LOG.trace("Will update external subnet {} with networkId {} and routerIds {}",
+                    subnetId, networkId, routerIds);
+            updateExternalSubnet(networkId, subnetId, routerIds);
+        } else {
+            LOG.trace("Will add external subnet {} with networkId {} and routerIds {}",
+                    subnetId, networkId, routerIds);
+            addExternalSubnet(networkId, subnetId, routerIds);
+        }
+    }
+
+    public void addExternalSubnet(Uuid networkId, Uuid subnetId, List<Uuid> routerIds) {
+        InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
+                .child(Subnets.class, new SubnetsKey(subnetId)).build();
+        try {
+            Subnets newExternalSubnets = createSubnets(subnetId, networkId, routerIds);
+            LOG.debug("Creating external subnet {}", newExternalSubnets);
+            SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier,
+                    newExternalSubnets);
+        } catch (TransactionCommitFailedException ex) {
+            LOG.error("Creation of External Subnets {} failed", subnetId, ex);
+        }
+    }
+
+    public void updateExternalSubnet(Uuid networkId, Uuid subnetId, List<Uuid> routerIds) {
+        InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
+                .child(Subnets.class, new SubnetsKey(subnetId)).build();
+        try {
+            Subnets newExternalSubnets = createSubnets(subnetId, networkId, routerIds);
+            LOG.debug("Updating external subnet {}", newExternalSubnets);
+            SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier,
+                    newExternalSubnets);
+        } catch (TransactionCommitFailedException ex) {
+            LOG.error("Update of External Subnets {} failed", subnetId, ex);
         }
     }
+
+    public void removeExternalSubnet(Uuid subnetId) {
+        InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
+                .child(Subnets.class, new SubnetsKey(subnetId)).build();
+        try {
+            LOG.debug("Removing external subnet {}", subnetId);
+            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
+        } catch (TransactionCommitFailedException ex) {
+            LOG.error("Deletion of External Subnets {} failed", subnetId, ex);
+        }
+    }
+
+    public void addRouterIdToExternalSubnet(Uuid networkId, Uuid subnetId, Uuid routerId) {
+        Optional<Subnets> optionalExternalSubnets = NeutronvpnUtils.getOptionalExternalSubnets(dataBroker, subnetId);
+        if (optionalExternalSubnets.isPresent()) {
+            Subnets subnets = optionalExternalSubnets.get();
+            List<Uuid> routerIds;
+            if (subnets.getRouterIds() != null) {
+                routerIds = subnets.getRouterIds();
+            } else {
+                routerIds = new ArrayList<>();
+            }
+
+            if (subnets.getExternalNetworkId() != null
+                    && subnets.getExternalNetworkId().equals(networkId) && !routerIds.contains(routerId)) {
+                LOG.debug("Will add routerID {} for external subnet.",
+                        routerId, subnetId);
+                routerIds.add(routerId);
+                updateExternalSubnet(networkId, subnetId, routerIds);
+            }
+        }
+    }
+
+    private Subnets createSubnets(Uuid subnetId, Uuid networkId, List<Uuid> routerIds) {
+        SubnetsBuilder subnetsBuilder = new SubnetsBuilder();
+        subnetsBuilder.setKey(new SubnetsKey(subnetId));
+        subnetsBuilder.setId(subnetId);
+        subnetsBuilder.setVpnId(subnetId);
+        subnetsBuilder.setExternalNetworkId(networkId);
+        if (routerIds != null) {
+            subnetsBuilder.setRouterIds(routerIds);
+        }
+
+        return subnetsBuilder.build();
+    }
+
+    private void updateExternalSubnetsForRouter(Uuid routerId, Uuid externalNetworkId,
+            List<ExternalFixedIps> externalFixedIps) {
+        LOG.debug("Updating external subnets for router {} for external network ID {}",
+                routerId, externalNetworkId);
+        Set<Uuid> subnetsUuidsSet = getExternalSubnetsUuidsSetForFixedIps(externalFixedIps);
+        for (Uuid subnetId : subnetsUuidsSet) {
+            addRouterIdToExternalSubnet(externalNetworkId, subnetId, routerId);
+        }
+    }
+
+    private void removeRouterFromExternalSubnets(Uuid routerId, Uuid externalNetworkId,
+            List<ExternalFixedIps> externalFixedIps) {
+        LOG.debug("Removing routerID {} from external subnets of external network{}",
+                routerId, externalNetworkId);
+
+        List<Subnets> fixedIpsSubnets = getSubnets(getExternalSubnetsUuidsSetForFixedIps(externalFixedIps));
+        for (Subnets subnets : fixedIpsSubnets) {
+            Uuid subnetId = subnets.getId();
+            List<Uuid> routerIds = subnets.getRouterIds();
+            if (routerIds != null) {
+                if (subnets.getExternalNetworkId() != null
+                        && subnets.getExternalNetworkId().equals(externalNetworkId)
+                        && routerIds.contains(routerId)) {
+                    routerIds.remove(routerId);
+                    LOG.debug("Will remove routerIDs {} from external subnet {} router ID {}",
+                        subnetId, routerId);
+                    addExternalSubnet(externalNetworkId, subnetId, routerIds);
+                }
+            }
+        }
+    }
+
+    private Set<Uuid> getExternalSubnetsUuidsSetForFixedIps(List<ExternalFixedIps> externalFixedIps) {
+        Set<Uuid> subnetsUuidsSet = new HashSet<>();
+        for (ExternalFixedIps externalFixedIp : externalFixedIps) {
+            subnetsUuidsSet.add(externalFixedIp.getSubnetId());
+        }
+
+        return subnetsUuidsSet;
+    }
+
+    private List<Subnets> getSubnets(Set<Uuid> subnetsUuidsSet) {
+        List<Subnets> subnetsList = new ArrayList<>();
+        for (Uuid subnetId : subnetsUuidsSet) {
+            Optional<Subnets> optionalSubnets = NeutronvpnUtils.getOptionalExternalSubnets(dataBroker, subnetId);
+            if (optionalSubnets.isPresent()) {
+                subnetsList.add(optionalSubnets.get());
+            }
+        }
+
+        return subnetsList;
+    }
+
+    private void addExternalFixedIpToExternalIpsList(List<ExternalIps> externalIps, ExternalFixedIps fixedIps) {
+        Uuid subnetId = fixedIps.getSubnetId();
+        String ip = fixedIps.getIpAddress().getIpv4Address().getValue();
+        ExternalIpsBuilder externalIpsBuilder = new ExternalIpsBuilder();
+        externalIpsBuilder.setKey(new ExternalIpsKey(ip, subnetId));
+        externalIpsBuilder.setIpAddress(ip);
+        externalIpsBuilder.setSubnetId(subnetId);
+        externalIps.add(externalIpsBuilder.build());
+    }
 }