use of com.google.common.util.concurrent.Futures in project Singularity by HubSpot.
the class S3LogResource method getS3LogsWithExecutorService.
// Fetching logs
private List<SingularityS3LogMetadata> getS3LogsWithExecutorService(S3Configuration s3Configuration, ListeningExecutorService executorService, Map<SingularityS3Service, Set<String>> servicesToPrefixes, int totalPrefixCount, final SingularityS3SearchRequest search, final ConcurrentHashMap<String, ContinuationToken> continuationTokens, final boolean paginated) throws InterruptedException, ExecutionException, TimeoutException {
List<ListenableFuture<List<S3ObjectSummaryHolder>>> futures = Lists.newArrayListWithCapacity(totalPrefixCount);
final AtomicInteger resultCount = new AtomicInteger();
for (final Map.Entry<SingularityS3Service, Set<String>> entry : servicesToPrefixes.entrySet()) {
final String s3Bucket = entry.getKey().getBucket();
final String group = entry.getKey().getGroup();
final AmazonS3 s3Client = entry.getKey().getS3Client();
for (final String s3Prefix : entry.getValue()) {
final String key = String.format(CONTINUATION_TOKEN_KEY_FORMAT, group, s3Bucket, s3Prefix);
if (search.getContinuationTokens().containsKey(key) && search.getContinuationTokens().get(key).isLastPage()) {
LOG.trace("No further content for prefix {} in bucket {}, skipping", s3Prefix, s3Bucket);
continuationTokens.putIfAbsent(key, search.getContinuationTokens().get(key));
continue;
}
futures.add(executorService.submit(new Callable<List<S3ObjectSummaryHolder>>() {
@Override
public List<S3ObjectSummaryHolder> call() throws Exception {
ListObjectsV2Request request = new ListObjectsV2Request().withBucketName(s3Bucket).withPrefix(s3Prefix);
if (paginated) {
Optional<ContinuationToken> token = Optional.empty();
if (search.getContinuationTokens().containsKey(key) && !Strings.isNullOrEmpty(search.getContinuationTokens().get(key).getValue())) {
request.setContinuationToken(search.getContinuationTokens().get(key).getValue());
token = Optional.of(search.getContinuationTokens().get(key));
}
int targetResultCount = search.getMaxPerPage().orElse(DEFAULT_TARGET_MAX_RESULTS);
request.setMaxKeys(targetResultCount);
if (resultCount.get() < targetResultCount) {
ListObjectsV2Result result = s3Client.listObjectsV2(request);
if (result.getObjectSummaries().isEmpty()) {
continuationTokens.putIfAbsent(key, new ContinuationToken(result.getNextContinuationToken(), true));
return Collections.emptyList();
} else {
boolean addToList = incrementIfLessThan(resultCount, result.getObjectSummaries().size(), targetResultCount);
if (addToList) {
continuationTokens.putIfAbsent(key, new ContinuationToken(result.getNextContinuationToken(), !result.isTruncated()));
List<S3ObjectSummaryHolder> objectSummaryHolders = new ArrayList<>();
for (S3ObjectSummary objectSummary : result.getObjectSummaries()) {
if (search.getFileNamePrefixWhitelist().isEmpty() || search.getFileNamePrefixWhitelist().stream().anyMatch(whitelistedPrefix -> objectSummary.getKey().startsWith(whitelistedPrefix))) {
objectSummaryHolders.add(new S3ObjectSummaryHolder(group, objectSummary));
}
}
return objectSummaryHolders;
} else {
continuationTokens.putIfAbsent(key, token.orElse(new ContinuationToken(null, false)));
return Collections.emptyList();
}
}
} else {
continuationTokens.putIfAbsent(key, token.orElse(new ContinuationToken(null, false)));
return Collections.emptyList();
}
} else {
ListObjectsV2Result result = s3Client.listObjectsV2(request);
List<S3ObjectSummaryHolder> objectSummaryHolders = new ArrayList<>();
for (S3ObjectSummary objectSummary : result.getObjectSummaries()) {
if (search.getFileNamePrefixWhitelist().isEmpty() || search.getFileNamePrefixWhitelist().stream().anyMatch(whitelistedPrefix -> objectSummary.getKey().startsWith(whitelistedPrefix))) {
objectSummaryHolders.add(new S3ObjectSummaryHolder(group, objectSummary));
}
}
while (result.isTruncated() && result.getContinuationToken() != null) {
result = s3Client.listObjectsV2(new ListObjectsV2Request().withBucketName(s3Bucket).withPrefix(s3Prefix).withContinuationToken(result.getContinuationToken()));
for (S3ObjectSummary objectSummary : result.getObjectSummaries()) {
objectSummaryHolders.add(new S3ObjectSummaryHolder(group, objectSummary));
}
}
return objectSummaryHolders;
}
}
}));
}
}
final long start = System.currentTimeMillis();
List<List<S3ObjectSummaryHolder>> results = Futures.allAsList(futures).get(s3Configuration.getWaitForS3ListSeconds(), TimeUnit.SECONDS);
List<S3ObjectSummaryHolder> objects = Lists.newArrayListWithExpectedSize(results.size() * 2);
for (List<S3ObjectSummaryHolder> s3ObjectSummaryHolders : results) {
for (final S3ObjectSummaryHolder s3ObjectHolder : s3ObjectSummaryHolders) {
objects.add(s3ObjectHolder);
}
}
LOG.trace("Got {} objects from S3 after {}", objects.size(), JavaUtils.duration(start));
List<ListenableFuture<SingularityS3LogMetadata>> logFutures = Lists.newArrayListWithCapacity(objects.size());
final Date expireAt = new Date(System.currentTimeMillis() + s3Configuration.getExpireS3LinksAfterMillis());
for (final S3ObjectSummaryHolder s3ObjectHolder : objects) {
final S3ObjectSummary s3Object = s3ObjectHolder.getObjectSummary();
final AmazonS3 s3Client = s3Services.getServiceByGroupAndBucketOrDefault(s3ObjectHolder.getGroup(), s3Object.getBucketName()).getS3Client();
logFutures.add(executorService.submit(new Callable<SingularityS3LogMetadata>() {
@Override
public SingularityS3LogMetadata call() throws Exception {
Optional<Long> maybeStartTime = Optional.empty();
Optional<Long> maybeEndTime = Optional.empty();
if (!search.isExcludeMetadata()) {
GetObjectMetadataRequest metadataRequest = new GetObjectMetadataRequest(s3Object.getBucketName(), s3Object.getKey());
Map<String, String> objectMetadata = s3Client.getObjectMetadata(metadataRequest).getUserMetadata();
maybeStartTime = getMetadataAsLong(objectMetadata, SingularityS3Log.LOG_START_S3_ATTR);
maybeEndTime = getMetadataAsLong(objectMetadata, SingularityS3Log.LOG_END_S3_ATTR);
}
if (search.isListOnly()) {
return new SingularityS3LogMetadata(s3Object.getKey(), s3Object.getLastModified().getTime(), s3Object.getSize(), maybeStartTime, maybeEndTime);
} else {
GeneratePresignedUrlRequest getUrlRequest = new GeneratePresignedUrlRequest(s3Object.getBucketName(), s3Object.getKey()).withMethod(HttpMethod.GET).withExpiration(expireAt);
String getUrl = s3Client.generatePresignedUrl(getUrlRequest).toString();
ResponseHeaderOverrides downloadHeaders = new ResponseHeaderOverrides();
downloadHeaders.setContentDisposition(CONTENT_DISPOSITION_DOWNLOAD_HEADER);
downloadHeaders.setContentEncoding(CONTENT_ENCODING_DOWNLOAD_HEADER);
GeneratePresignedUrlRequest downloadUrlRequest = new GeneratePresignedUrlRequest(s3Object.getBucketName(), s3Object.getKey()).withMethod(HttpMethod.GET).withExpiration(expireAt).withResponseHeaders(downloadHeaders);
String downloadUrl = s3Client.generatePresignedUrl(downloadUrlRequest).toString();
return new SingularityS3Log(getUrl, s3Object.getKey(), s3Object.getLastModified().getTime(), s3Object.getSize(), downloadUrl, maybeStartTime, maybeEndTime);
}
}
}));
}
return Futures.allAsList(logFutures).get(s3Configuration.getWaitForS3LinksSeconds(), TimeUnit.SECONDS);
}
use of com.google.common.util.concurrent.Futures in project netvirt by opendaylight.
the class VpnInterfaceManager method addVpnInterfaceToVpn.
private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier, final VpnInterface vpnInterface, @Nullable final List<Adjacency> oldAdjs, @Nullable final List<Adjacency> newAdjs, final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class);
final String interfaceName = key.getName();
String primaryRd = vpnUtil.getPrimaryRd(vpnName);
if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
if (interfaceState != null) {
try {
final Uint64 dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
final int ifIndex = interfaceState.getIfIndex();
jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName, () -> {
// TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
// (the inventory tx goes in last)
List<ListenableFuture<?>> futures = new ArrayList<>();
// set of prefix used, as entry in prefix-to-interface datastore
// is prerequisite for refresh Fib to avoid race condition leading to
// missing remote next hop in bucket actions on bgp-vpn delete
Set<String> prefixListForRefreshFib = new HashSet<>();
ListenableFuture<?> confFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, invTx -> {
LOG.info("addVpnInterface: VPN Interface add event - intfName {} vpnName {}" + " on dpn {}", vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false, confTx, operTx, invTx, interfaceState, vpnName, prefixListForRefreshFib);
if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}" + " Update for swapping VPN {} case.", interfaceName, vpnName);
if (newAdjs != null) {
for (Adjacency adj : newAdjs) {
if (oldAdjs.contains(adj)) {
oldAdjs.remove(adj);
} else {
if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj, dpnId, operTx, confTx, invTx, prefixListForRefreshFib);
}
}
}
}
for (Adjacency adj : oldAdjs) {
if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId, operTx, confTx);
}
}
}
})))));
Futures.addCallback(confFuture, new VpnInterfaceCallBackHandler(primaryRd, prefixListForRefreshFib), MoreExecutors.directExecutor());
futures.add(confFuture);
Futures.addCallback(confFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"), MoreExecutors.directExecutor());
LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}" + " processed successfully", interfaceName, vpnName, dpnId);
return futures;
});
} catch (NumberFormatException | IllegalStateException e) {
LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for " + "interface {}. Interface addition on vpn {} failed", interfaceName, vpnName, e);
return;
}
} else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
ListenableFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName, confTx, vpnName);
LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName, vpnName, vpnInterface.getDpnId());
});
LoggingFutures.addErrorLogging(future, LOG, "Error creating FIB entry for interface {} on VPN {}", vpnInterface.getName(), vpnName);
return Collections.singletonList(future);
});
} else {
LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState" + " is not available", interfaceName, vpnName);
}
} else {
LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped" + " as vpn is pending delete", interfaceName, vpnName, vpnInterface.getDpnId());
}
}
use of com.google.common.util.concurrent.Futures in project netvirt by opendaylight.
the class TunnelEndPointChangeListener method add.
@Override
public void add(InstanceIdentifier<TunnelEndPoints> key, TunnelEndPoints tep) {
Uint64 dpnId = key.firstIdentifierOf(DPNTEPsInfo.class).firstKeyOf(DPNTEPsInfo.class).getDPNID();
if (Uint64.ZERO.equals(dpnId)) {
LOG.warn("add: Invalid DPN id for TEP {}", tep.getInterfaceName());
return;
}
List<VpnInstance> vpnInstances = VpnHelper.getAllVpnInstances(broker);
if (vpnInstances == null || vpnInstances.isEmpty()) {
LOG.warn("add: dpnId: {}: tep: {}: No VPN instances defined", dpnId, tep.getInterfaceName());
return;
}
for (VpnInstance vpnInstance : vpnInstances) {
final String vpnName = vpnInstance.getVpnInstanceName();
final Uint32 vpnId = vpnUtil.getVpnId(vpnName);
LOG.info("add: Handling TEP {} add for VPN instance {}", tep.getInterfaceName(), vpnName);
final String primaryRd = vpnUtil.getPrimaryRd(vpnName);
if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
List<VpnInterfaces> vpnInterfaces = vpnUtil.getDpnVpnInterfaces(vpnInstance, dpnId);
if (vpnInterfaces != null) {
for (VpnInterfaces vpnInterface : vpnInterfaces) {
String vpnInterfaceName = vpnInterface.getInterfaceName();
jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(broker, vpnInterfaceName);
if (interfaceState == null) {
LOG.debug("add: Cannot retrieve interfaceState for vpnInterfaceName {}, " + "cannot generate lPortTag and process adjacencies", vpnInterfaceName);
return Collections.emptyList();
}
final int lPortTag = interfaceState.getIfIndex();
List<ListenableFuture<?>> futures = new ArrayList<>();
Set<String> prefixesForRefreshFib = new HashSet<>();
ListenableFuture<?> writeConfigFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeOperTxn -> futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeInvTxn -> vpnInterfaceManager.processVpnInterfaceAdjacencies(dpnId, lPortTag, vpnName, primaryRd, vpnInterfaceName, vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState, prefixesForRefreshFib))))));
Futures.addCallback(writeConfigFuture, new FutureCallback<Object>() {
@Override
public void onSuccess(Object voidObj) {
prefixesForRefreshFib.forEach(prefix -> {
fibManager.refreshVrfEntry(primaryRd, prefix);
});
}
@Override
public void onFailure(Throwable throwable) {
LOG.debug("addVpnInterface: write Tx config execution failed", throwable);
}
}, MoreExecutors.directExecutor());
futures.add(writeConfigFuture);
LOG.trace("add: Handled TEP {} add for VPN instance {} VPN interface {}", tep.getInterfaceName(), vpnName, vpnInterfaceName);
return futures;
});
}
}
} else {
LOG.error("add: Ignoring addition of tunnel interface {} dpn {} for vpnInstance {} with primaryRd {}," + " as the VPN is already marked for deletion", tep.getInterfaceName(), dpnId, vpnName, primaryRd);
}
}
}
use of com.google.common.util.concurrent.Futures in project netvirt by opendaylight.
the class InterfaceStateChangeListener method update.
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
@Override
public void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
final String ifName = update.getName();
try {
if (update.getIfIndex() == null) {
return;
}
if (L2vlan.class.equals(update.getType())) {
LOG.info("VPN Interface update event - intfName {} from InterfaceStateChangeListener", update.getName());
jobCoordinator.enqueueJob("VPNINTERFACE-" + ifName, () -> {
List<ListenableFuture<?>> futures = new ArrayList<>(3);
futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeOperTxn -> {
// map of prefix and vpn name used, as entry in prefix-to-interface datastore
// is prerequisite for refresh Fib to avoid race condition leading to missing remote
// next hop in bucket actions on bgp-vpn delete
Map<String, Set<String>> mapOfRdAndPrefixesForRefreshFib = new HashMap<>();
ListenableFuture<?> configTxFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, writeConfigTxn -> futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeInvTxn -> {
final VpnInterface vpnIf = vpnUtil.getConfiguredVpnInterface(ifName);
if (vpnIf != null) {
final int ifIndex = update.getIfIndex();
Uint64 dpnId;
try {
dpnId = InterfaceUtils.getDpIdFromInterface(update);
} catch (Exception e) {
LOG.error("remove: Unable to retrieve dpnId for interface {}", ifName, e);
return;
}
IntfTransitionState state = getTransitionState(original.getOperStatus(), update.getOperStatus());
if (state.equals(IntfTransitionState.STATE_IGNORE)) {
LOG.info("InterfaceStateChangeListener: Interface {} state " + "original {}" + "updated {} not handled", ifName, original.getOperStatus(), update.getOperStatus());
return;
}
LOG.error("InterfaceStateChangeListener- Processing ifState {} " + "update event " + "with dpnId {} operstate {}", ifName, dpnId, update.getOperStatus());
if (state.equals(IntfTransitionState.STATE_UP) && vpnIf.getVpnInstanceNames() != null) {
for (VpnInstanceNames vpnInterfaceVpnInstance : vpnIf.getVpnInstanceNames().values()) {
String vpnName = vpnInterfaceVpnInstance.getVpnName();
String primaryRd = vpnUtil.getPrimaryRd(vpnName);
Set<String> prefixes = new HashSet<>();
if (!vpnInterfaceManager.isVpnInstanceReady(vpnName)) {
LOG.error("VPN Interface update event - intfName {} " + "onto vpnName {} running oper-driven UP, " + "VpnInstance not ready, holding on", vpnIf.getName(), vpnName);
} else if (vpnUtil.isVpnPendingDelete(primaryRd)) {
LOG.error("update: Ignoring UP event for vpnInterface " + "{}, as vpnInstance {} with primaryRd {} is " + "already marked for deletion ", vpnIf.getName(), vpnName, primaryRd);
} else {
vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnIf, primaryRd, ifIndex, true, writeConfigTxn, writeOperTxn, writeInvTxn, update, vpnName, prefixes);
mapOfRdAndPrefixesForRefreshFib.put(primaryRd, prefixes);
}
}
} else if (state.equals(IntfTransitionState.STATE_DOWN) && vpnIf.getVpnInstanceNames() != null) {
for (VpnInstanceNames vpnInterfaceVpnInstance : vpnIf.getVpnInstanceNames().values()) {
String vpnName = vpnInterfaceVpnInstance.getVpnName();
LOG.info("VPN Interface update event - intfName {} " + " onto vpnName {} running oper-driven DOWN", vpnIf.getName(), vpnName);
Optional<VpnInterfaceOpDataEntry> optVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(vpnIf.getName(), vpnName);
if (optVpnInterface.isPresent()) {
VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
vpnInterfaceManager.processVpnInterfaceDown(dpnId, vpnIf.getName(), ifIndex, update.getPhysAddress().getValue(), vpnOpInterface, true, writeConfigTxn, writeOperTxn, writeInvTxn);
} else {
LOG.error("InterfaceStateChangeListener Update DOWN - " + " vpnInterface {}not available, ignoring event", vpnIf.getName());
continue;
}
}
}
} else {
LOG.debug("Interface {} is not a vpninterface, ignoring.", ifName);
}
})));
Futures.addCallback(configTxFuture, new VpnInterfaceCallBackHandler(mapOfRdAndPrefixesForRefreshFib), MoreExecutors.directExecutor());
futures.add(configTxFuture);
}));
return futures;
});
}
} catch (Exception e) {
LOG.error("Exception observed in handling updation of VPN Interface {}. ", update.getName(), e);
}
}
use of com.google.common.util.concurrent.Futures in project netvirt by opendaylight.
the class ExternalRoutersListener method update.
@Override
public void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
if (natMode != NatMode.Controller) {
return;
}
LOG.trace("update : origRouter: {} updatedRouter: {}", original, update);
String routerName = original.getRouterName();
Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
if (routerId == NatConstants.INVALID_ID) {
LOG.error("update : external router event - Invalid routerId for routerName {}", routerName);
return;
}
coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + update.key(), () -> {
List<ListenableFuture<?>> futures = new ArrayList<>();
futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeFlowInvTx -> {
futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, removeFlowInvTx -> {
Uint32 bgpVpnId = NatConstants.INVALID_ID;
Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
if (bgpVpnUuid != null) {
bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
}
// BigInteger dpnId = getPrimaryNaptSwitch(routerName);
/* Get Primary Napt Switch for existing router from "router-to-napt-switch" DS.
* if dpnId value is null or zero then go for electing new Napt switch for existing router.
*/
Uint64 dpnId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
boolean isPrimaryNaptSwitchNotSelected = (dpnId == null || dpnId.equals(Uint64.valueOf(BigInteger.ZERO)));
Uuid networkId = original.getNetworkId();
// Check if its update on SNAT flag
boolean originalSNATEnabled = original.isEnableSnat();
boolean updatedSNATEnabled = update.isEnableSnat();
LOG.debug("update :called with originalFlag and updatedFlag for SNAT enabled " + "as {} and {} with Elected Dpn {}(isPrimaryNaptSwitchNotSelected:{})", originalSNATEnabled, updatedSNATEnabled, dpnId, isPrimaryNaptSwitchNotSelected);
// 3. First Elect dpnId and process other changes with valid dpnId
if (originalSNATEnabled != updatedSNATEnabled || isPrimaryNaptSwitchNotSelected) {
if (originalSNATEnabled && !updatedSNATEnabled) {
if (isPrimaryNaptSwitchNotSelected) {
LOG.info("No Action to be taken when SNAT is disabled " + "with no Napt Switch Election for Router {}", routerName);
return;
}
// SNAT disabled for the router
Uuid networkUuid = original.getNetworkId();
LOG.info("update : SNAT disabled for Router {}", routerName);
Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
handleDisableSnat(original, networkUuid, externalIps, false, vpnName, dpnId, routerId, removeFlowInvTx);
} else if (updatedSNATEnabled) {
LOG.info("update : SNAT enabled for Router {}", routerName);
addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, true, writeFlowInvTx);
if (isPrimaryNaptSwitchNotSelected) {
dpnId = selectNewNAPTSwitch(routerName);
if (dpnId != null && !dpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
handleEnableSnat(update, routerId, dpnId, bgpVpnId, removeFlowInvTx);
} else {
LOG.error("update : Failed to elect Napt Switch During update event" + " of router {}", routerName);
}
}
}
LOG.info("update : no need to process external/subnet changes as it's will taken care" + "in handleDisableSnat/handleEnableSnat");
return;
}
if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
NatUtil.installRouterGwFlows(txRunner, vpnManager, original, dpnId, NwConstants.DEL_FLOW);
NatUtil.installRouterGwFlows(txRunner, vpnManager, update, dpnId, NwConstants.ADD_FLOW);
}
if (updatedSNATEnabled != originalSNATEnabled) {
LOG.info("update : no need to process external/subnet changes as it's will taken care in " + "handleDisableSnat/handleEnableSnat");
return;
}
// Check if the Update is on External IPs
LOG.debug("update : Checking if this is update on External IPs for router {}", routerName);
List<String> originalExternalIps = NatUtil.getIpsListFromExternalIps(new ArrayList<ExternalIps>(original.nonnullExternalIps().values()));
List<String> updatedExternalIps = NatUtil.getIpsListFromExternalIps(new ArrayList<ExternalIps>(update.nonnullExternalIps().values()));
// Check if the External IPs are removed during the update.
Set<String> removedExternalIps = new HashSet<>(originalExternalIps);
removedExternalIps.removeAll(updatedExternalIps);
if (removedExternalIps.size() > 0) {
LOG.debug("update : Start processing of the External IPs removal for router {}", routerName);
vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName, removedExternalIps, original.getExtGwMacAddress(), dpnId, networkId);
for (String removedExternalIp : removedExternalIps) {
/*
1) Remove the mappings in the IntExt IP model which has external IP.
2) Remove the external IP in the ExternalCounter model.
3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the
least loaded external IP.
Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
4) Increase the count of the allocated external IP by one.
5) Advertise to the BGP if external IP is allocated for the first time for the router
i.e. the route for the external IP is absent.
6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for
the removed external IPs and also from the model.
7) Advertise to the BGP for removing the route for the removed external IPs.
*/
String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
String externalIp = externalIpParts[0];
String externalIpPrefix = externalIpParts[1];
String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
LOG.debug("update : Clear the routes from the BGP and remove the FIB and TS " + "entries for removed external IP {}", externalIpAddrStr);
Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
String vpnName = "";
if (vpnUuId != null) {
vpnName = vpnUuId.getValue();
}
clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName, networkId, update.getExtGwMacAddress(), removeFlowInvTx);
LOG.debug("update : Remove the mappings in the IntExtIP model which has external IP.");
// Get the internal IPs which are associated to the removed external IPs
List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
List<String> removedInternalIps = new ArrayList<>();
for (IpMap ipMap : ipMaps) {
if (ipMap.getExternalIp().equals(externalIpAddrStr)) {
removedInternalIps.add(ipMap.getInternalIp());
}
}
LOG.debug("update : Remove the mappings of the internal IPs from the IntExtIP model.");
for (String removedInternalIp : removedInternalIps) {
LOG.debug("update : Remove the IP mapping of the internal IP {} for the " + "router ID {} from the IntExtIP model", removedInternalIp, routerId);
naptManager.removeFromIpMapDS(routerId, removedInternalIp);
}
LOG.debug("update : Remove the count mapping of the external IP {} for the " + "router ID {} from the ExternalIpsCounter model.", externalIpAddrStr, routerId);
naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
LOG.debug("update : Allocate the least loaded external IPs to the subnets " + "whose external IPs were removed.");
for (String removedInternalIp : removedInternalIps) {
allocateExternalIp(dpnId, update, routerId, routerName, networkId, removedInternalIp, writeFlowInvTx);
}
LOG.debug("update : Remove the NAPT translation entries from " + "Inbound and Outbound NAPT tables for the removed external IPs.");
// Get the internalIP and internal Port which were associated to the removed external IP.
Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
Optional<IpPortMapping> ipPortMapping;
try {
ipPortMapping = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
} catch (InterruptedException | ExecutionException e) {
LOG.error("Failed to read ipPortMapping for router id {}", routerId, e);
ipPortMapping = Optional.empty();
}
if (ipPortMapping.isPresent()) {
for (IntextIpProtocolType intextIpProtocolType : ipPortMapping.get().nonnullIntextIpProtocolType().values()) {
ProtocolTypes protoType = intextIpProtocolType.getProtocol();
for (IpPortMap ipPortMap : intextIpProtocolType.nonnullIpPortMap().values()) {
IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
if (ipPortExternal.getIpAddress().equals(externalIp)) {
List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
if (removedInternalIpPorts != null) {
removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
} else {
removedInternalIpPorts = new ArrayList<>();
removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
}
}
}
}
}
// Remove the IP port map from the intext-ip-port-map model, which were containing
// the removed external IP.
Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
Map<String, List<String>> internalIpPortMap = new HashMap<>();
for (Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts) {
ProtocolTypes protocolType = (ProtocolTypes) protoTypesIntIpPort.getKey();
List<String> removedInternalIpPorts = (List<String>) protoTypesIntIpPort.getValue();
for (String removedInternalIpPort : removedInternalIpPorts) {
// Remove the IP port map from the intext-ip-port-map model,
// which were containing the removed external IP
naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
// Remove the IP port incomint packer map.
naptPacketInHandler.removeIncomingPacketMap(routerId + NatConstants.COLON_SEPARATOR + removedInternalIpPort);
String[] removedInternalIpPortParts = removedInternalIpPort.split(NatConstants.COLON_SEPARATOR);
if (removedInternalIpPortParts.length == 2) {
String removedInternalIp = removedInternalIpPortParts[0];
String removedInternalPort = removedInternalIpPortParts[1];
List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
if (removedInternalPortsList != null) {
removedInternalPortsList.add(removedInternalPort);
internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
naptPacketInHandler.removeIncomingPacketMap(routerId + NatConstants.COLON_SEPARATOR + removedInternalIp + NatConstants.COLON_SEPARATOR + removedInternalPort);
// Remove the NAPT translation entries from Outbound NAPT table
naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, removedInternalIp, Integer.parseInt(removedInternalPort), protocolType.getName());
naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, removedInternalIp, Integer.parseInt(removedInternalPort), protocolType.getName());
} else {
removedInternalPortsList = new ArrayList<>();
removedInternalPortsList.add(removedInternalPort);
internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
naptPacketInHandler.removeIncomingPacketMap(routerId + NatConstants.COLON_SEPARATOR + removedInternalIp + NatConstants.COLON_SEPARATOR + removedInternalPort);
// Remove the NAPT translation entries from Outbound NAPT table
naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, removedInternalIp, Integer.parseInt(removedInternalPort), protocolType.getName());
naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, removedInternalIp, Integer.parseInt(removedInternalPort), protocolType.getName());
}
}
}
}
// Delete the entry from SnatIntIpPortMap DS
Set<String> internalIps = internalIpPortMap.keySet();
for (String internalIp : internalIps) {
LOG.debug("update : Removing IpPort having the internal IP {} from the " + "model SnatIntIpPortMap", internalIp);
naptManager.removeFromSnatIpPortDS(routerId, internalIp);
}
naptManager.removeNaptPortPool(externalIp);
}
LOG.debug("update : End processing of the External IPs removal for router {}", routerName);
}
// Check if the External IPs are added during the update.
Set<String> addedExternalIps = new HashSet<>(updatedExternalIps);
addedExternalIps.removeAll(originalExternalIps);
if (addedExternalIps.size() != 0) {
LOG.debug("update : Start processing of the External IPs addition for router {}", routerName);
vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps, update.getExtGwMacAddress(), dpnId, update.getNetworkId());
for (String addedExternalIp : addedExternalIps) {
/*
1) Do nothing in the IntExtIp model.
2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
*/
String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
String externalIp = externalIpParts[0];
String externalIpPrefix = externalIpParts[1];
String externalpStr = externalIp + "/" + externalIpPrefix;
LOG.debug("update : Initialise the count mapping of the external IP {} for the " + "router ID {} in the ExternalIpsCounter model.", externalpStr, routerId);
naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
subnetRegisterMapping(update, routerId);
LOG.info("update : Installing fib flow fo newly added Ips");
handleSnatReverseTraffic(writeFlowInvTx, dpnId, update, routerId, routerName, externalpStr);
}
LOG.debug("update : End processing of the External IPs addition during the update operation");
}
// Check if its Update on subnets
LOG.debug("update : Checking if this is update on subnets for router {}", routerName);
List<Uuid> originalSubnetIds = original.getSubnetIds();
List<Uuid> updatedSubnetIds = update.getSubnetIds();
Set<Uuid> addedSubnetIds = updatedSubnetIds != null ? new HashSet<>(updatedSubnetIds) : new HashSet<>();
if (originalSubnetIds != null) {
addedSubnetIds.removeAll(originalSubnetIds);
}
// Check if the Subnet IDs are added during the update.
if (addedSubnetIds.size() != 0) {
LOG.debug("update : Start processing of the Subnet IDs addition for router {}", routerName);
for (Uuid addedSubnetId : addedSubnetIds) {
/*
1) Select the least loaded external IP for the subnet and store the mapping of the
subnet IP and the external IP in the IntExtIp model.
2) Increase the count of the selected external IP by one.
3) Advertise to the BGP if external IP is allocated for the first time for the
router i.e. the route for the external IP is absent.
*/
String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
if (subnetIp != null) {
allocateExternalIp(dpnId, update, routerId, routerName, networkId, subnetIp, writeFlowInvTx);
}
}
LOG.debug("update : End processing of the Subnet IDs addition for router {}", routerName);
}
// Check if the Subnet IDs are removed during the update.
Set<Uuid> removedSubnetIds = new HashSet<>(originalSubnetIds);
removedSubnetIds.removeAll(updatedSubnetIds);
if (removedSubnetIds.size() != 0) {
LOG.debug("update : Start processing of the Subnet IDs removal for router {}", routerName);
for (Uuid removedSubnetId : removedSubnetIds) {
String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
if (subnetAddr != null) {
/*
1) Remove the subnet IP and the external IP in the IntExtIp map
2) Decrease the count of the coresponding external IP by one.
3) Advertise to the BGP for removing the routes of the corresponding external
IP if its not allocated to any other internal IP.
*/
String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
if (externalIp == null) {
LOG.error("update : No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
return;
}
naptManager.updateCounter(routerId, externalIp, false);
// used by any other internal ip in any router
if (!isExternalIpAllocated(externalIp)) {
LOG.debug("update : external ip is not allocated to any other " + "internal IP so proceeding to remove routes");
clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, Collections.singleton(externalIp), null, update.getExtGwMacAddress(), removeFlowInvTx);
LOG.debug("update : Successfully removed fib entries in switch {} for " + "router {} with networkId {} and externalIp {}", dpnId, routerId, networkId, externalIp);
}
LOG.debug("update : Remove the IP mapping for the router ID {} and " + "internal IP {} external IP {}", routerId, subnetAddr[0], externalIp);
naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
}
}
LOG.debug("update : End processing of the Subnet IDs removal for router {}", routerName);
}
}));
}));
return futures;
}, NatConstants.NAT_DJC_MAX_RETRIES);
}
Aggregations