X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=natservice%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Fnatservice%2Fha%2FWeightedCentralizedSwitchScheduler.java;h=69d93ed215381307b793b8f7e55aa46980eaa912;hb=97c8a6961453727e929878b58399626485382a1f;hp=dce1357832b52e3c6fe648f1299711bf65f612f7;hpb=daa85fec597b538b9ca6b74dd9aa4d138a07e235;p=netvirt.git diff --git a/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/ha/WeightedCentralizedSwitchScheduler.java b/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/ha/WeightedCentralizedSwitchScheduler.java index dce1357832..69d93ed215 100644 --- a/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/ha/WeightedCentralizedSwitchScheduler.java +++ b/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/ha/WeightedCentralizedSwitchScheduler.java @@ -11,30 +11,30 @@ package org.opendaylight.netvirt.natservice.ha; import static org.opendaylight.genius.infra.Datastore.CONFIGURATION; import static org.opendaylight.genius.infra.Datastore.OPERATIONAL; -import com.google.common.base.Optional; - -import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; - 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.ReadFailedException; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.genius.datastoreutils.ExpectedDataObjectNotFoundException; import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; import org.opendaylight.genius.infra.ManagedNewTransactionRunner; import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; -import org.opendaylight.infrautils.utils.concurrent.ListenableFutures; +import org.opendaylight.infrautils.utils.concurrent.LoggingFutures; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler; +import org.opendaylight.netvirt.natservice.api.NatSwitchCache; +import org.opendaylight.netvirt.natservice.api.NatSwitchCacheListener; +import org.opendaylight.netvirt.natservice.api.SwitchInfo; import org.opendaylight.netvirt.natservice.internal.NatUtil; import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; @@ -44,6 +44,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches; 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.routers.ExternalIps; +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.napt.switches.RouterToNaptSwitch; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey; @@ -52,15 +53,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060 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.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.Uint64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton -public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchScheduler { +public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchScheduler, NatSwitchCacheListener { private static final Logger LOG = LoggerFactory.getLogger(WeightedCentralizedSwitchScheduler.class); private static final Integer INITIAL_SWITCH_WEIGHT = Integer.valueOf(0); - private final Map> providerSwitchWeightsMap = new ConcurrentHashMap<>(); + private final Map> providerSwitchWeightsMap = new ConcurrentHashMap<>(); private final Map subnetIdToRouterPortMap = new ConcurrentHashMap<>(); private final Map subnetIdToElanInstanceMap = new ConcurrentHashMap<>(); private final DataBroker dataBroker; @@ -70,8 +72,10 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche private final NatserviceConfig.NatMode natMode; @Inject - public WeightedCentralizedSwitchScheduler(DataBroker dataBroker, OdlInterfaceRpcService interfaceManager, - IVpnFootprintService vpnFootprintService, final NatserviceConfig config) { + public WeightedCentralizedSwitchScheduler(final DataBroker dataBroker, + final OdlInterfaceRpcService interfaceManager, + final IVpnFootprintService vpnFootprintService, final NatserviceConfig config, + final NatSwitchCache natSwitchCache) { this.dataBroker = dataBroker; this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); this.interfaceManager = interfaceManager; @@ -81,13 +85,14 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche } else { this.natMode = NatserviceConfig.NatMode.Controller; } + natSwitchCache.register(this); } @Override public boolean scheduleCentralizedSwitch(Routers router) { String providerNet = NatUtil.getElanInstancePhysicalNetwok(router.getNetworkId().getValue(),dataBroker); - BigInteger nextSwitchId = getSwitchWithLowestWeight(providerNet); - if (nextSwitchId == BigInteger.valueOf(0)) { + Uint64 nextSwitchId = getSwitchWithLowestWeight(providerNet); + if (Uint64.ZERO.equals(nextSwitchId)) { LOG.error("In scheduleCentralizedSwitch, unable to schedule the router {} as there is no available switch.", router.getRouterName()); return false; @@ -103,7 +108,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche try { SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier(routerName), id); - Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); + Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); switchWeightMap.put(nextSwitchId,switchWeightMap.get(nextSwitchId) + 1); } catch (TransactionCommitFailedException e) { @@ -119,7 +124,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche String routerName = newRouter.getRouterName(); List addedSubnetIds = getUpdatedSubnetIds(newRouter.getSubnetIds(), oldRouter.getSubnetIds()); List deletedSubnetIds = getUpdatedSubnetIds(oldRouter.getSubnetIds(), newRouter.getSubnetIds()); - BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, newRouter.getRouterName()); + Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, newRouter.getRouterName()); addToDpnMaps(routerName, addedSubnetIds, primarySwitchId); deleteFromDpnMaps(routerName, deletedSubnetIds, primarySwitchId); try { @@ -127,8 +132,8 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche RouterToNaptSwitch routerToNaptSwitch = SingleTransactionDataBroker.syncRead(dataBroker, LogicalDatastoreType.CONFIGURATION, id); boolean isSnatEnabled = newRouter.isEnableSnat(); - List updateExternalIps = newRouter.getExternalIps(); - if (updateExternalIps == null || updateExternalIps.isEmpty()) { + Map updateExternalIpsMap = newRouter.getExternalIps(); + if (updateExternalIpsMap == null || updateExternalIpsMap.isEmpty()) { isSnatEnabled = false; } if (isSnatEnabled != routerToNaptSwitch.isEnableSnat()) { @@ -138,7 +143,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier(routerName), routerToNaptSwitchBuilder.build()); } - } catch (ReadFailedException e) { + } catch (ExpectedDataObjectNotFoundException e) { LOG.error("updateCentralizedSwitch ReadFailedException for {}", routerName); } catch (TransactionCommitFailedException e) { LOG.error("updateCentralizedSwitch TransactionCommitFailedException for {}", routerName); @@ -150,8 +155,8 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche public boolean releaseCentralizedSwitch(Routers router) { String providerNet = NatUtil.getElanInstancePhysicalNetwok(router.getNetworkId().getValue(),dataBroker); String routerName = router.getRouterName(); - BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName); - if (primarySwitchId == null || primarySwitchId == BigInteger.valueOf(0)) { + Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName); + if (primarySwitchId == null || Uint64.ZERO.equals(primarySwitchId)) { LOG.info("releaseCentralizedSwitch: NAPT Switch is not allocated for router {}", router.getRouterName()); return false; } @@ -161,7 +166,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche try { SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier(routerName)); - Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); + Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); switchWeightMap.put(primarySwitchId, switchWeightMap.get(primarySwitchId) - 1); } catch (TransactionCommitFailedException e) { return false; @@ -169,7 +174,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche return true; } - private void addToDpnMaps(String routerName, List addedSubnetIds, BigInteger primarySwitchId) { + private void addToDpnMaps(String routerName, List addedSubnetIds, Uint64 primarySwitchId) { if (addedSubnetIds == null || addedSubnetIds.isEmpty()) { LOG.debug("addToDpnMaps no subnets associated with {}", routerName); return; @@ -178,14 +183,14 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche try { String primaryRd = txRunner.applyWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> { for (Uuid subnetUuid : addedSubnetIds) { - Subnetmap subnetMapEntry = tx.read(getSubnetMapIdentifier(subnetUuid)).get().orNull(); + Subnetmap subnetMapEntry = tx.read(getSubnetMapIdentifier(subnetUuid)).get().orElse(null); subnetMapEntries.put(subnetUuid, subnetMapEntry); Uuid routerPortUuid = subnetMapEntry.getRouterInterfacePortId(); subnetIdToRouterPortMap.put(subnetUuid.getValue(), routerPortUuid.getValue()); } return NatUtil.getPrimaryRd(routerName, tx); }).get(); - ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> { + LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> { for (Uuid subnetUuid : addedSubnetIds) { Subnetmap subnetMapEntry = subnetMapEntries.get(subnetUuid); Uuid routerPortUuid = subnetMapEntry.getRouterInterfacePortId(); @@ -205,9 +210,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche } } - - - private void deleteFromDpnMaps(String routerName, List deletedSubnetIds, BigInteger primarySwitchId) { + private void deleteFromDpnMaps(String routerName, List deletedSubnetIds, Uint64 primarySwitchId) { if (deletedSubnetIds == null || deletedSubnetIds.isEmpty()) { LOG.debug("deleteFromDpnMaps no subnets associated with {}", routerName); return; @@ -215,7 +218,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche try { String primaryRd = txRunner.applyWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> NatUtil.getPrimaryRd(routerName, tx)).get(); - ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> { + LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> { for (Uuid subnetUuid : deletedSubnetIds) { String routerPort = subnetIdToRouterPortMap.remove(subnetUuid.getValue()); if (routerPort == null) { @@ -240,35 +243,33 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche } @Override - public boolean addSwitch(BigInteger dpnId) { - /* Initialize the switch in the map with weight 0 */ - LOG.info("addSwitch: Retrieving the provider config for {}", dpnId); + public void switchAddedToCache(SwitchInfo switchInfo) { boolean scheduleRouters = (providerSwitchWeightsMap.size() == 0) ? true : false; - Map providerMappingsMap = NatUtil.getOpenvswitchOtherConfigMap(dpnId, dataBroker); - for (String providerNet : providerMappingsMap.keySet()) { - Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); + for (String providerNet : switchInfo.getProviderNets()) { + Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); if (providerSwitchWeightsMap.get(providerNet) == null) { switchWeightMap = new ConcurrentHashMap<>(); providerSwitchWeightsMap.put(providerNet, switchWeightMap); } - LOG.info("addSwitch: Adding {} dpnId with provider mapping {} to switchWeightsMap", dpnId, providerNet); - switchWeightMap.put(dpnId, INITIAL_SWITCH_WEIGHT); + LOG.info("addSwitch: Adding {} dpnId with provider mapping {} to switchWeightsMap", + switchInfo.getDpnId(), providerNet); + switchWeightMap.put(switchInfo.getDpnId(), INITIAL_SWITCH_WEIGHT); } if (natMode == NatserviceConfig.NatMode.Conntrack && scheduleRouters) { Optional optRouters; try { optRouters = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(ExtRouters.class)); - } catch (ReadFailedException e) { + } catch (InterruptedException | ExecutionException e) { LOG.error("addSwitch: Error reading external routers", e); - return false; + return; } if (optRouters.isPresent()) { // Get the list of routers and verify if any routers do not have primarySwitch allocated. - for (Routers router : optRouters.get().getRouters()) { - List externalIps = router.getExternalIps(); - if (router.isEnableSnat() && externalIps != null && !externalIps.isEmpty()) { + for (Routers router : optRouters.get().nonnullRouters().values()) { + Map keyExternalIpsMap = router.getExternalIps(); + if (router.isEnableSnat() && keyExternalIpsMap != null && !keyExternalIpsMap.isEmpty()) { // Check if the primarySwitch is allocated for the router. if (!isPrimarySwitchAllocatedForRouter(router.getRouterName())) { scheduleCentralizedSwitch(router); @@ -277,7 +278,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche } } } - return true; + return; } private boolean isPrimarySwitchAllocatedForRouter(String routerName) { @@ -286,11 +287,11 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche try { RouterToNaptSwitch rtrToNapt = SingleTransactionDataBroker.syncRead(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch); - BigInteger dpnId = rtrToNapt.getPrimarySwitchId(); - if (dpnId == null || dpnId.equals(BigInteger.ZERO)) { + Uint64 dpnId = rtrToNapt.getPrimarySwitchId(); + if (dpnId == null || dpnId.equals(Uint64.ZERO)) { return false; } - } catch (ReadFailedException e) { + } catch (ExpectedDataObjectNotFoundException e) { LOG.error("isPrimarySwitchAllocatedForRouter: Error reading RouterToNaptSwitch model", e); return false; } @@ -298,14 +299,15 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche } @Override - public boolean removeSwitch(BigInteger dpnId) { + public void switchRemovedFromCache(SwitchInfo switchInfo) { + Uint64 dpnId = switchInfo.getDpnId(); LOG.info("removeSwitch: Removing {} dpnId to switchWeightsMap", dpnId); - for (Map.Entry> providerNet : providerSwitchWeightsMap.entrySet()) { - Map switchWeightMap = providerNet.getValue(); + for (Map.Entry> providerNet : providerSwitchWeightsMap.entrySet()) { + Map switchWeightMap = providerNet.getValue(); if (natMode == NatserviceConfig.NatMode.Conntrack && !INITIAL_SWITCH_WEIGHT.equals(switchWeightMap.get(dpnId))) { NaptSwitches naptSwitches = getNaptSwitches(); - for (RouterToNaptSwitch routerToNaptSwitch : naptSwitches.getRouterToNaptSwitch()) { + for (RouterToNaptSwitch routerToNaptSwitch : naptSwitches.nonnullRouterToNaptSwitch().values()) { if (dpnId.equals(routerToNaptSwitch.getPrimarySwitchId())) { Routers router = NatUtil.getRoutersFromConfigDS(dataBroker, routerToNaptSwitch.getRouterName()); releaseCentralizedSwitch(router); @@ -316,25 +318,30 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche } switchWeightMap.remove(dpnId); } - return true; + return; } private NaptSwitches getNaptSwitches() { InstanceIdentifier id = InstanceIdentifier.builder(NaptSwitches.class).build(); - return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker, - LogicalDatastoreType.CONFIGURATION, id).orNull(); + try { + return SingleTransactionDataBroker.syncReadOptional(dataBroker, + LogicalDatastoreType.CONFIGURATION, id).orElse(null); + } catch (ExecutionException | InterruptedException e) { + LOG.error("getNaptSwitches: Exception while reading Napt-Switch DS", e); + } + return null; } - private BigInteger getSwitchWithLowestWeight(String providerNet) { + private Uint64 getSwitchWithLowestWeight(String providerNet) { int lowestWeight = Integer.MAX_VALUE; - BigInteger nextSwitchId = BigInteger.valueOf(0); - Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); + Uint64 nextSwitchId = Uint64.valueOf(0); + Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); if (null == switchWeightMap) { LOG.error("No switch have the provider mapping {}", providerNet); return nextSwitchId; } - for (Entry entry : switchWeightMap.entrySet()) { - BigInteger dpnId = entry.getKey(); + for (Entry entry : switchWeightMap.entrySet()) { + Uint64 dpnId = entry.getKey(); Integer weight = entry.getValue(); if (lowestWeight > weight) { lowestWeight = weight; @@ -356,7 +363,8 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche new SubnetmapKey(subnetId)).build(); } - public BigInteger getCentralizedSwitch(String routerName) { + @Nullable + public Uint64 getCentralizedSwitch(String routerName) { try { Optional naptSwitches = SingleTransactionDataBroker .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, @@ -366,24 +374,14 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche return null; } return naptSwitches.get().getPrimarySwitchId(); - } catch (ReadFailedException e) { + } catch (InterruptedException | ExecutionException e) { LOG.error("Error reading RouterToNaptSwitch model", e); return null; } } - @Override - public boolean isSwitchConnectedToExternal(BigInteger dpnId, String providerNet) { - Map switchWeightMap = providerSwitchWeightsMap.get(providerNet); - if (switchWeightMap != null) { - return switchWeightMap.containsKey(dpnId); - } - return false; - } - - public static List getUpdatedSubnetIds( - List updatedSubnetIds, - List currentSubnetIds) { + @Nullable + private static List getUpdatedSubnetIds(List updatedSubnetIds, List currentSubnetIds) { if (updatedSubnetIds == null) { return null; }