NETVIRT-1201 Upstream fixes to master --- 8
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnUtils.java
index 3af9c815b040d04b4e51953700507394f749d746..4d9763ed8d1c3abf9dc248601dd9cc7916c3e9ce 100644 (file)
@@ -29,17 +29,24 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
 import javax.annotation.Nonnull;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+
 import org.apache.commons.lang3.StringUtils;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
@@ -62,14 +69,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.Dhcpv6Base;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.PortsSubnetIpPrefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpVersionBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.PortSubnets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.PortSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.PortSubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.PortSubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.port.subnet.SubnetInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.port.subnet.SubnetInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.port.subnet.SubnetInfoKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeFlat;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeGre;
@@ -108,12 +121,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIdsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.ext.rev150712.NetworkL3Extension;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
 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.RouterKey;
+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.networks.rev150712.NetworkTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeFlat;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeGre;
@@ -176,14 +192,16 @@ public class NeutronvpnUtils {
     private final ConcurrentMap<Uuid, HashMap<Uuid, Network>> qosNetworksMap = new ConcurrentHashMap<>();
 
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IdManagerService idManager;
     private final JobCoordinator jobCoordinator;
-    private IPV6InternetDefaultRouteProgrammer ipV6InternetDefRt;
+    private final IPV6InternetDefaultRouteProgrammer ipV6InternetDefRt;
 
     @Inject
     public NeutronvpnUtils(final DataBroker dataBroker, final IdManagerService idManager,
             final JobCoordinator jobCoordinator, final IPV6InternetDefaultRouteProgrammer ipV6InternetDefRt) {
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.idManager = idManager;
         this.jobCoordinator = jobCoordinator;
         this.ipV6InternetDefRt = ipV6InternetDefRt;
@@ -250,7 +268,7 @@ public class NeutronvpnUtils {
     }
 
     // @param external vpn - true if external vpn being fetched, false for internal vpn
-    protected Uuid getVpnForRouter(Uuid routerId, Boolean externalVpn) {
+    protected Uuid getVpnForRouter(Uuid routerId, boolean externalVpn) {
         if (routerId == null) {
             return null;
         }
@@ -260,7 +278,14 @@ public class NeutronvpnUtils {
         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
             List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
             for (VpnMap vpnMap : allMaps) {
-                if (routerId.equals(vpnMap.getRouterId())) {
+                List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap
+                    .RouterIds> routerIdsList = vpnMap.getRouterIds();
+                if (routerIdsList == null || routerIdsList.isEmpty()) {
+                    continue;
+                }
+                List<Uuid> rtrIdsList = routerIdsList.stream().map(routerIds -> routerIds.getRouterId())
+                        .collect(Collectors.toList());
+                if (rtrIdsList.contains(routerId)) {
                     if (externalVpn) {
                         if (!routerId.equals(vpnMap.getVpnId())) {
                             return vpnMap.getVpnId();
@@ -277,15 +302,15 @@ public class NeutronvpnUtils {
         return null;
     }
 
-    protected Uuid getRouterforVpn(Uuid vpnId) {
+    protected List<Uuid> getRouterIdListforVpn(Uuid vpnId) {
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap.class,
                 new VpnMapKey(vpnId)).build();
         Optional<VpnMap> optionalVpnMap = read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
         if (optionalVpnMap.isPresent()) {
             VpnMap vpnMap = optionalVpnMap.get();
-            return vpnMap.getRouterId();
+            return NeutronUtils.getVpnMapRouterIdsListUuid(vpnMap.getRouterIds());
         }
-        LOG.error("getRouterforVpn: Failed as VPNMaps DS is absent for VPN {}", vpnId.getValue());
+        LOG.error("getRouterIdListforVpn: Failed as VPNMaps DS is absent for VPN {}", vpnId.getValue());
         return null;
     }
 
@@ -361,6 +386,12 @@ public class NeutronvpnUtils {
         return router;
     }
 
+    public InstanceIdentifier<Router> getNeutronRouterIid(Uuid routerId) {
+        return InstanceIdentifier.create(Neutron.class).child(Routers.class).child(Router
+                .class, new RouterKey(routerId));
+
+    }
+
     protected Network getNeutronNetwork(Uuid networkId) {
         Network network = null;
         network = networkMap.get(networkId);
@@ -406,7 +437,7 @@ public class NeutronvpnUtils {
             // router interface, dhcp port and floating ip.
             return false;
         }
-        PortSecurityExtension portSecurity = port.getAugmentation(PortSecurityExtension.class);
+        PortSecurityExtension portSecurity = port.augmentation(PortSecurityExtension.class);
         if (portSecurity != null) {
             return portSecurity.isPortSecurityEnabled();
         }
@@ -507,7 +538,7 @@ public class NeutronvpnUtils {
                 .AllowedAddressPairs allowedAddressPair1 = iterator.next();
             for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes
                      .AllowedAddressPairs allowedAddressPair2 : list2) {
-                if (allowedAddressPair1.getKey().equals(allowedAddressPair2.getKey())) {
+                if (allowedAddressPair1.key().equals(allowedAddressPair2.key())) {
                     iterator.remove();
                     break;
                 }
@@ -689,35 +720,46 @@ public class NeutronvpnUtils {
         interfaceAclBuilder.setAllowedAddressPairs(aclAllowedAddressPairs);
     }
 
-    protected void populateSubnetIpPrefixes(Port port) {
-        List<IpPrefixOrAddress> subnetIpPrefixes = getSubnetIpPrefixes(port);
-        if (subnetIpPrefixes != null) {
+    protected void populateSubnetInfo(Port port) {
+        List<SubnetInfo> portSubnetInfo = getSubnetInfo(port);
+        if (portSubnetInfo != null) {
             String portId = port.getUuid().getValue();
-            InstanceIdentifier<PortSubnetIpPrefixes> portSubnetIpPrefixIdentifier =
-                NeutronvpnUtils.buildPortSubnetIpPrefixIdentifier(portId);
-            PortSubnetIpPrefixesBuilder subnetIpPrefixesBuilder = new PortSubnetIpPrefixesBuilder()
-                    .setKey(new PortSubnetIpPrefixesKey(portId)).setPortId(portId)
-                    .setSubnetIpPrefixes(subnetIpPrefixes);
-            MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portSubnetIpPrefixIdentifier,
-                    subnetIpPrefixesBuilder.build());
-            LOG.debug("Created Subnet IP Prefixes for port {}", port.getUuid().getValue());
+            InstanceIdentifier<PortSubnet> portSubnetIdentifier = buildPortSubnetIdentifier(portId);
+
+            PortSubnetBuilder portSubnetBuilder = new PortSubnetBuilder().withKey(new PortSubnetKey(portId))
+                    .setPortId(portId).setSubnetInfo(portSubnetInfo);
+            try {
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
+                        portSubnetIdentifier, portSubnetBuilder.build());
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("Failed to populate subnet info for port={}", portId, e);
+            }
+            LOG.debug("Created Subnet info for port={}", portId);
         }
     }
 
-    protected List<IpPrefixOrAddress> getSubnetIpPrefixes(Port port) {
-        List<Uuid> subnetIds = getSubnetIdsFromNetworkId(port.getNetworkId());
-        if (subnetIds == null) {
-            LOG.error("Failed to get Subnet Ids for the Network {}", port.getNetworkId());
+    protected List<SubnetInfo> getSubnetInfo(Port port) {
+        List<FixedIps> portFixedIps = port.getFixedIps();
+        if (portFixedIps == null) {
+            LOG.error("Failed to get Fixed IPs for the port {}", port.getName());
             return null;
         }
-        List<IpPrefixOrAddress> subnetIpPrefixes = new ArrayList<>();
-        for (Uuid subnetId : subnetIds) {
+        List<SubnetInfo> subnetInfoList = new ArrayList<>();
+        for (FixedIps portFixedIp : portFixedIps) {
+            Uuid subnetId = portFixedIp.getSubnetId();
             Subnet subnet = getNeutronSubnet(subnetId);
             if (subnet != null) {
-                subnetIpPrefixes.add(new IpPrefixOrAddress(subnet.getCidr()));
+                Class<? extends IpVersionBase> ipVersion =
+                        NeutronSecurityRuleConstants.IP_VERSION_MAP.get(subnet.getIpVersion());
+                Class<? extends Dhcpv6Base> raMode = subnet.getIpv6RaMode() == null ? null
+                        : NeutronSecurityRuleConstants.RA_MODE_MAP.get(subnet.getIpv6RaMode());
+                SubnetInfo subnetInfo = new SubnetInfoBuilder().withKey(new SubnetInfoKey(subnetId))
+                        .setIpVersion(ipVersion).setIpPrefix(new IpPrefixOrAddress(subnet.getCidr()))
+                        .setIpv6RaMode(raMode).setGatewayIp(subnet.getGatewayIp()).build();
+                subnetInfoList.add(subnetInfo);
             }
         }
-        return subnetIpPrefixes;
+        return subnetInfoList;
     }
 
     protected Subnet getNeutronSubnet(Uuid subnetId) {
@@ -731,6 +773,7 @@ public class NeutronvpnUtils {
 
         if (sn.isPresent()) {
             subnet = sn.get();
+            addToSubnetCache(subnet);
         }
         return subnet;
     }
@@ -786,7 +829,7 @@ public class NeutronvpnUtils {
             boolean isSubnetIp, WriteTransaction writeConfigTxn) {
         InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier(vpnName, fixedIp);
         VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder()
-            .setKey(new VpnPortipToPortKey(fixedIp, vpnName))
+            .withKey(new VpnPortipToPortKey(fixedIp, vpnName))
             .setVpnName(vpnName).setPortFixedip(fixedIp)
             .setPortName(portName).setMacAddress(macAddress).setSubnetIp(isSubnetIp);
         try {
@@ -886,7 +929,7 @@ public class NeutronvpnUtils {
 
     public static String getSegmentationIdFromNeutronNetwork(Network network) {
         String segmentationId = null;
-        NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+        NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
         if (providerExtension != null) {
             Class<? extends NetworkTypeBase> networkType = providerExtension.getNetworkType();
             segmentationId = NeutronUtils.getSegmentationIdFromNeutronNetwork(network, networkType);
@@ -896,12 +939,12 @@ public class NeutronvpnUtils {
     }
 
     public static Class<? extends SegmentTypeBase> getSegmentTypeFromNeutronNetwork(Network network) {
-        NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+        NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
         return providerExtension != null ? NETWORK_MAP.get(providerExtension.getNetworkType()) : null;
     }
 
     public static String getPhysicalNetworkName(Network network) {
-        NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+        NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
         return providerExtension != null ? providerExtension.getPhysicalNetwork() : null;
     }
 
@@ -924,8 +967,8 @@ public class NeutronvpnUtils {
     }
 
     static Boolean getIsExternal(Network network) {
-        return network.getAugmentation(NetworkL3Extension.class) != null
-                && network.getAugmentation(NetworkL3Extension.class).isExternal();
+        return network.augmentation(NetworkL3Extension.class) != null
+                && network.augmentation(NetworkL3Extension.class).isExternal();
     }
 
     public void addToQosPolicyCache(QosPolicy qosPolicy) {
@@ -1010,9 +1053,9 @@ public class NeutronvpnUtils {
                 FloatingIpIdToPortMappingKey(floatingIpId)).build();
     }
 
-    static InstanceIdentifier<PortSubnetIpPrefixes> buildPortSubnetIpPrefixIdentifier(String portId) {
-        InstanceIdentifier<PortSubnetIpPrefixes> id = InstanceIdentifier.builder(PortsSubnetIpPrefixes.class)
-            .child(PortSubnetIpPrefixes.class, new PortSubnetIpPrefixesKey(portId)).build();
+    static InstanceIdentifier<PortSubnet> buildPortSubnetIdentifier(String portId) {
+        InstanceIdentifier<PortSubnet> id = InstanceIdentifier.builder(PortSubnets.class)
+                .child(PortSubnet.class, new PortSubnetKey(portId)).build();
         return id;
     }
 
@@ -1027,7 +1070,7 @@ public class NeutronvpnUtils {
     }
 
     public static Class<? extends NetworkTypeBase> getNetworkType(Network network) {
-        NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+        NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
         return providerExtension != null ? providerExtension.getNetworkType() : null;
     }
 
@@ -1036,7 +1079,7 @@ public class NeutronvpnUtils {
             LOG.error("Error in getting provider network type since network is null");
             return null;
         }
-        NetworkProviderExtension npe = network.getAugmentation(NetworkProviderExtension.class);
+        NetworkProviderExtension npe = network.augmentation(NetworkProviderExtension.class);
         if (npe != null) {
             Class<? extends NetworkTypeBase> networkTypeBase = npe.getNetworkType();
             if (networkTypeBase != null) {
@@ -1057,12 +1100,12 @@ public class NeutronvpnUtils {
     }
 
     static boolean isNetworkTypeSupported(Network network) {
-        NetworkProviderExtension npe = network.getAugmentation(NetworkProviderExtension.class);
+        NetworkProviderExtension npe = network.augmentation(NetworkProviderExtension.class);
         return npe != null && npe.getNetworkType() != null && SUPPORTED_NETWORK_TYPES.contains(npe.getNetworkType());
     }
 
     static boolean isNetworkOfType(Network network, Class<? extends NetworkTypeBase> type) {
-        NetworkProviderExtension npe = network.getAugmentation(NetworkProviderExtension.class);
+        NetworkProviderExtension npe = network.augmentation(NetworkProviderExtension.class);
         if (npe != null && npe.getNetworkType() != null) {
             return type.isAssignableFrom(npe.getNetworkType());
         }
@@ -1112,7 +1155,6 @@ public class NeutronvpnUtils {
         return Optional.absent();
     }
 
-
     public Set<RouterDpnList> getAllRouterDpnList(BigInteger dpid) {
         Set<RouterDpnList> ret = new HashSet<>();
         InstanceIdentifier<NeutronRouterDpns> routerDpnId =
@@ -1156,8 +1198,7 @@ public class NeutronvpnUtils {
     protected void releaseRDId(String poolName, String idKey) {
         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
         try {
-            Future<RpcResult<Void>> result = idManager.releaseId(idInput);
-            RpcResult<Void> rpcResult = result.get();
+            RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
             if (!rpcResult.isSuccessful()) {
                 LOG.error("RPC Call to Get Unique Id returned with errors for poolname {} and ID Key {}: {}",
                         poolName, idKey, rpcResult.getErrors());
@@ -1179,7 +1220,7 @@ public class NeutronvpnUtils {
            3. Use the prefix "FE80::/10" along with the above 64 bit Interface
               identifier to generate the IPv6 LLA. */
 
-        StringBuffer interfaceID = new StringBuffer();
+        StringBuilder interfaceID = new StringBuilder();
         short u8byte = (short) (octets[0] & 0xff);
         u8byte ^= 1 << 1;
         interfaceID.append(Integer.toHexString(0xFF & u8byte));
@@ -1346,7 +1387,7 @@ public class NeutronvpnUtils {
      */
     public static IpVersionChoice getIpVersionFromString(String ipAddress) {
         IpVersionChoice ipchoice = IpVersionChoice.UNDEFINED;
-        if (ipAddress.indexOf("/") >= 0) {
+        if (ipAddress.contains("/")) {
             ipAddress = ipAddress.substring(0, ipAddress.indexOf("/"));
         }
         try {
@@ -1481,17 +1522,16 @@ public class NeutronvpnUtils {
             if (isFinalVpnInstanceIpv6Changed) {
                 builder.setIpv6Configured(finalIsIpv6Configured);
             }
-            WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
-            InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
-                    .child(VpnInstanceOpDataEntry.class,
-                            new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
-            writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
-            LOG.info("updateVpnInstanceWithIpFamily: Successfully {} {} to Vpn {}",
-                    add ? "added" : "removed",
-                    ipVersion.toString(), vpnName);
-            return Collections.singletonList(writeTxn.submit());
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
+                        .child(VpnInstanceOpDataEntry.class,
+                                new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
+                tx.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
+                LOG.info("updateVpnInstanceWithIpFamily: Successfully {} {} to Vpn {}",
+                        add ? "added" : "removed",
+                        ipVersion.toString(), vpnName);
+            }));
         });
-        return;
     }
 
     /**
@@ -1508,7 +1548,7 @@ public class NeutronvpnUtils {
         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class,
                 new VpnInstanceKey(vpnId.getValue())).build();
         Optional<VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
-        return (vpnInstance.isPresent()) ? vpnInstance.get() : null;
+        return vpnInstance.isPresent() ? vpnInstance.get() : null;
     }
 
     /**
@@ -1553,51 +1593,31 @@ public class NeutronvpnUtils {
     }
 
     /**
-     * Get all subnetmap associate to the belonging router of network.
-     * @param network the network which have router bound
-     * @return a list of Subnetmap of the router (which the network is associated)
+     * Get a list of Private Subnetmap Ids from router to export then its prefixes in Internet VPN.
+     * @param extNet Provider Network, which has a port attached as external network gateway to router
+     * @return a list of Private Subnetmap Ids of the router with external network gateway
      */
-    public @Nonnull List<Subnetmap> getSubnetMapsforNetworkRoute(@Nonnull Network network) {
-        List<Subnetmap> subList = new ArrayList<>();
-        LOG.debug("getSubnetMapsforNetworkRoute for network {}", network.getUuid());
-        Uuid vpnUuid = getVpnForNetwork(network.getUuid());
-        InstanceIdentifier<Subnetmaps> subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build();
-        Optional<Subnetmaps> optionalSubnetmaps = read(LogicalDatastoreType.CONFIGURATION,
-                       subnetmapsid);
-        if (!optionalSubnetmaps.isPresent()) {
-            LOG.debug("getSubnetMapsforNetworkRoute: no subnetmaps");
-            return Collections.emptyList();
-        }
-        List<Subnetmap> subnetmapList = optionalSubnetmaps.get().getSubnetmap();
-        if (vpnUuid != null) {
-            for (Subnetmap subnetmap : subnetmapList) {
-                if ((subnetmap.getInternetVpnId() != null)
-                     && subnetmap.getInternetVpnId().getValue().equals(vpnUuid.getValue())) {
-                    subList.add(subnetmap);
-                }
-            }
-        } else {
-            Uuid routerId = null;
-            for (Subnetmap subnetmap : subnetmapList) {
-                if (subnetmap.getRouterId() != null) {
-                    Uuid externalNetworkUuid = getExternalNetworkUuidAttachedFromRouterUuid(subnetmap.getRouterId());
-                    if (externalNetworkUuid != null && externalNetworkUuid.getValue()
-                         .equals(network.getUuid().getValue())) {
-                        routerId = subnetmap.getRouterId();
-                        break;
-                    }
-                }
-            }
-            if (routerId == null) {
-                LOG.debug("getSubnetMapsforNetworkRoute: no subnet in routers using {}", network.getUuid());
-                return Collections.emptyList();
+    public @Nonnull List<Uuid> getPrivateSubnetsToExport(@Nonnull Network extNet) {
+        List<Uuid> subList = new ArrayList<>();
+        Uuid extNetVpnId = getVpnForNetwork(extNet.getUuid());
+        if (extNetVpnId == null) {
+            return subList;
+        }
+        for (Uuid rtrId: getRouterIdListforVpn(extNetVpnId)) {
+            Router router = getNeutronRouter(rtrId);
+            ExternalGatewayInfo info = router.getExternalGatewayInfo();
+            if (info == null) {
+                LOG.error("getPrivateSubnetsToExport: can not get info about external gateway for router {}",
+                          router.getUuid().getValue());
+                continue;
             }
-            for (Subnetmap subnetmap : subnetmapList) {
-                if (subnetmap.getRouterId() != null
-                        && subnetmap.getRouterId().getValue().matches(routerId.getValue())) {
-                    subList.add(subnetmap);
-                }
+            // check that router really has given provider network as its external gateway port
+            if (!extNet.getUuid().equals(info.getExternalNetworkId())) {
+                LOG.error("getPrivateSubnetsToExport: router {} is not attached to given provider network {}",
+                          router.getUuid().getValue(), extNet.getUuid().getValue());
+                continue;
             }
+            subList.addAll(getSubnetsforVpn(rtrId));
         }
         return subList;
     }
@@ -1605,25 +1625,30 @@ public class NeutronvpnUtils {
     public void updateVpnInstanceWithFallback(String vpnName, boolean add) {
         VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName);
         if (vpnInstanceOpDataEntry == null) {
-            // BGPVPN context not found
+            LOG.error("updateVpnInstanceWithFallback: vpnInstanceOpDataEntry not found for vpn {}", vpnName);
             return;
         }
-        String routerIdUuid = getRouterIdfromVpnInstance(vpnInstanceOpDataEntry.getVrfId());
-        if (routerIdUuid != null) {
-            List<BigInteger> dpnIds = getDpnsForRouter(routerIdUuid);
-            if (!dpnIds.isEmpty()) {
-                Long vpnId = vpnInstanceOpDataEntry.getVpnId();
-                VpnInstanceOpDataEntry vpnOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(routerIdUuid);
-                Long routerIdAsLong = vpnOpDataEntry.getVpnId();
-                if (routerIdAsLong == null) {
-                    return;
-                }
-                for (BigInteger dpnId : dpnIds) {
-                    if (add) {
-                        ipV6InternetDefRt.installDefaultRoute(dpnId, vpnId, routerIdAsLong);
-                    } else {
-                        ipV6InternetDefRt.removeDefaultRoute(dpnId, vpnId, routerIdAsLong);
-                    }
+        Long vpnId = vpnInstanceOpDataEntry.getVpnId();
+        List<Uuid> routerIds = getRouterIdsfromVpnInstance(vpnInstanceOpDataEntry.getVrfId());
+        if ((routerIds == null) || (routerIds.isEmpty())) {
+            LOG.error("updateVpnInstanceWithFallback: router not found for vpn {}", vpnName);
+            return;
+        }
+        for (Uuid rtrId: routerIds) {
+            if (rtrId == null) {
+                continue;
+            }
+            List<BigInteger> dpnIds = getDpnsForRouter(rtrId.getValue());
+            if (dpnIds.isEmpty()) {
+                continue;
+            }
+            VpnInstanceOpDataEntry vpnOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(rtrId.getValue());
+            Long routerIdAsLong = vpnOpDataEntry.getVpnId();
+            for (BigInteger dpnId : dpnIds) {
+                if (add) {
+                    ipV6InternetDefRt.installDefaultRoute(dpnId, vpnId, routerIdAsLong);
+                } else {
+                    ipV6InternetDefRt.removeDefaultRoute(dpnId, vpnId, routerIdAsLong);
                 }
             }
         }
@@ -1654,17 +1679,73 @@ public class NeutronvpnUtils {
         }
         VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder(vpnInstanceOpDataEntry);
         builder.setBgpvpnType(choice);
-        WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
-        writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
-        LOG.debug("updateVpnInstanceOpWithType: sent merge to operDS BgpvpnType {} for {}", choice, vpn.getValue());
-        try {
-            writeTxn.submit().get();
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("updateVpnInstanceOpWithType: on merge execution, error:  {}", e);
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            tx.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
+            LOG.debug("updateVpnInstanceOpWithType: sent merge to operDS BgpvpnType {} for {}", choice, vpn.getValue());
+        }), LOG, "Error updating VPN instance op {} with type {}", vpn, choice);
+    }
+
+    public List<Uuid> getAssociateRouterInputRouterIdsListUuid(List<RouterIds> routerIds) {
+        if (routerIds == null) {
+            return Collections.emptyList();
+        }
+        return routerIds.stream().map(
+            routerId -> routerId.getRouterId()).collect(Collectors.toList());
+    }
+
+    public List<Uuid> getDisassociateRouterInputRouterIdsListUuid(List<RouterIds> routerIds) {
+        if (routerIds == null) {
+            return Collections.emptyList();
+        }
+        return routerIds.stream().map(
+            routerId -> routerId.getRouterId()).collect(Collectors.toList());
+    }
+
+    public RouterIds getvpnMapRouterIds(Uuid routerId) {
+        return new RouterIdsBuilder().setRouterId(routerId).build();
+    }
+
+    public void removeVpnMapRouterIdsFromList(Uuid routerId, List<RouterIds> vpnRouterIds) {
+        Iterator<RouterIds> vpnRouterIdIter = vpnRouterIds.iterator();
+        while (vpnRouterIdIter.hasNext()) {
+            RouterIds vpnRouterId = vpnRouterIdIter.next();
+            if (vpnRouterId.getRouterId().getValue().equals(routerId.getValue())) {
+                vpnRouterIdIter.remove();
+                return;
+            }
         }
         return;
     }
 
+    public boolean vpnMapRouterIdsContainsRouterId(Uuid routerId, List<RouterIds> vpnRouterIds) {
+        if (routerId == null) {
+            return false;
+        }
+        return vpnRouterIds.stream().anyMatch(vpnRouterId ->
+              vpnRouterId.getRouterId().getValue().equals(routerId.getValue()));
+    }
+
+    public List<Uuid> getVpnInstanceRouterIdsListUuid(List<RouterIds> routerIds) {
+        if (routerIds == null) {
+            return Collections.emptyList();
+        }
+        return routerIds.stream().map(
+            routerId -> routerId.getRouterId()).collect(Collectors.toList());
+    }
+
+    public static RouterIds getvpnInstanceRouterIds(Uuid routerId) {
+        return new RouterIdsBuilder().setRouterId(routerId).build();
+    }
+
+    public static List<RouterIds> getVpnInstanceRouterIdsList(List<Uuid> routerIds) {
+        List<RouterIds> listRouterIds = new ArrayList<>();
+        for (Uuid routerId : routerIds) {
+            final RouterIds routerIdInstance = getvpnInstanceRouterIds(routerId);
+            listRouterIds.add(routerIdInstance);
+        }
+        return listRouterIds;
+    }
+
     @Nonnull
     public List<BigInteger> getDpnsForRouter(String routerUuid) {
         InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class)
@@ -1682,7 +1763,7 @@ public class NeutronvpnUtils {
         return dpns;
     }
 
-    public String getRouterIdfromVpnInstance(String vpnName) {
+    public List<Uuid> getRouterIdsfromVpnInstance(String vpnName) {
         // returns only router, attached to IPv4 networks
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
             .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
@@ -1690,15 +1771,13 @@ public class NeutronvpnUtils {
                 .syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                         LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
         if (!optionalVpnMap.isPresent()) {
-            LOG.error("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
+            LOG.error("getRouterIdsfromVpnInstance : Router not found for vpn : {}", vpnName);
             return null;
         }
-        Uuid routerId = optionalVpnMap.get().getRouterId();
-        if (routerId != null) {
-            return routerId.getValue();
-        }
-        LOG.info("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
-        return null;
+        List<Uuid> rtrIds = optionalVpnMap.get().getRouterIds().stream().map(routerIds -> routerIds.getRouterId())
+                .collect(Collectors.toList());
+        return rtrIds;
+
     }
 
     public InstanceIdentifier<Router> buildNeutronRouterIdentifier(Uuid routerUuid) {
@@ -1706,4 +1785,24 @@ public class NeutronvpnUtils {
              .child(Routers.class).child(Router.class, new RouterKey(routerUuid));
         return routerInstanceIdentifier;
     }
+
+    List<Subnetmap> getSubnetmapListFromNetworkId(Uuid networkId) {
+        List<Uuid> subnetIdList = getSubnetIdsFromNetworkId(networkId);
+        if (subnetIdList != null) {
+            List<Subnetmap> subnetmapList = new ArrayList<>();
+            for (Uuid subnetId : subnetIdList) {
+                Subnetmap subnetmap = getSubnetmap(subnetId);
+                if (subnetmap != null) {
+                    subnetmapList.add(subnetmap);
+                } else {
+                    LOG.error("getSubnetmapListFromNetworkId: subnetmap is null for subnet {} belonging to network {}",
+                            subnetId.getValue(), networkId.getValue());
+                }
+            }
+            return subnetmapList;
+        }
+        LOG.error("getSubnetmapListFromNetworkId: Failed as subnetIdList is null for network {}",
+                networkId.getValue());
+        return null;
+    }
 }