2 * Copyright (c) 2017 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.natservice.internal;
11 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
13 import java.util.Collections;
15 import java.util.Optional;
16 import java.util.concurrent.ExecutionException;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
21 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
22 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
25 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
26 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
27 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
28 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.mdsal.common.api.ReadFailedException;
31 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
32 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredSyncDataTreeChangeListener;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.upgrade.rev180702.UpgradeConfig;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.common.Uint32;
46 import org.opendaylight.yangtools.yang.common.Uint64;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
51 public class UpgradeStateListener extends AbstractClusteredSyncDataTreeChangeListener<UpgradeConfig> {
52 private static final Logger LOG = LoggerFactory.getLogger(UpgradeStateListener.class);
54 private final DataBroker dataBroker;
55 private final CentralizedSwitchScheduler centralizedSwitchScheduler;
56 private final NatserviceConfig.NatMode natMode;
57 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
58 private IMdsalApiManager mdsalManager;
59 private IdManagerService idManager;
60 private final NaptSwitchHA naptSwitchHA;
61 private final JobCoordinator coordinator;
62 private final ManagedNewTransactionRunner txRunner;
65 public UpgradeStateListener(final DataBroker dataBroker,
66 final CentralizedSwitchScheduler centralizedSwitchScheduler,
67 final SNATDefaultRouteProgrammer defaultRouteProgrammer,
68 final IMdsalApiManager mdsalManager,
69 final IdManagerService idManager,
70 final NaptSwitchHA naptSwitchHA,
71 final NatserviceConfig config, final JobCoordinator coordinator) {
72 super(dataBroker, DataTreeIdentifier.create(
73 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(UpgradeConfig.class)));
74 this.dataBroker = dataBroker;
75 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
76 this.centralizedSwitchScheduler = centralizedSwitchScheduler;
77 this.defaultRouteProgrammer = defaultRouteProgrammer;
78 this.mdsalManager = mdsalManager;
79 this.idManager = idManager;
80 this.coordinator = coordinator;
81 this.naptSwitchHA = naptSwitchHA;
83 this.natMode = config.getNatMode();
85 this.natMode = NatserviceConfig.NatMode.Controller;
87 LOG.trace("UpgradeStateListener (nat) initialized");
91 public void add(@NonNull UpgradeConfig newDataObject) {
95 public void remove(@NonNull UpgradeConfig removedDataObject) {
96 if (natMode == NatserviceConfig.NatMode.Conntrack) {
99 LOG.debug("Verify is all Elected Napt Switch and connected back post upgrade");
103 public void update(@NonNull UpgradeConfig original, UpgradeConfig updated) {
104 if (natMode == NatserviceConfig.NatMode.Controller) {
105 if (original.isUpgradeInProgress() && !updated.isUpgradeInProgress()) {
106 Optional<NaptSwitches> npatSwitches = NatUtil.getAllPrimaryNaptSwitches(dataBroker);
107 if (npatSwitches.isPresent()) {
108 for (RouterToNaptSwitch routerToNaptSwitch
109 : npatSwitches.get().nonnullRouterToNaptSwitch().values()) {
110 Uint64 primaryNaptDpnId = routerToNaptSwitch.getPrimarySwitchId();
111 if (!NatUtil.getSwitchStatus(dataBroker, routerToNaptSwitch.getPrimarySwitchId())) {
112 String routerUuid = routerToNaptSwitch.getRouterName();
113 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerUuid,
114 () -> Collections.singletonList(
115 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
116 confTx -> reElectNewNaptSwitch(routerUuid, primaryNaptDpnId, confTx)
117 )), NatConstants.NAT_DJC_MAX_RETRIES);
125 LOG.info("UpgradeStateListener update from {} to {}", original, updated);
126 if (!(original.isUpgradeInProgress() && !updated.isUpgradeInProgress())) {
130 SingleTransactionDataBroker reader = new SingleTransactionDataBroker(dataBroker);
133 routers = reader.syncRead(LogicalDatastoreType.CONFIGURATION,
134 InstanceIdentifier.create(ExtRouters.class));
135 } catch (ReadFailedException e) {
136 LOG.error("Error reading external routers", e);
140 for (Routers router : routers.nonnullRouters().values()) {
141 Map<ExternalIpsKey, ExternalIps> keyExternalIpsMap = router.nonnullExternalIps();
142 if (router.isEnableSnat() && keyExternalIpsMap != null && !keyExternalIpsMap.isEmpty()) {
143 centralizedSwitchScheduler.scheduleCentralizedSwitch(router);
148 private void reElectNewNaptSwitch(String routerName, Uint64 primaryNaptDpnId,
149 TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
150 // Check if this is externalRouter else ignore
151 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
152 Optional<Routers> routerData =
153 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
154 LogicalDatastoreType.CONFIGURATION, extRoutersId);
155 if (!routerData.isPresent()) {
156 LOG.debug("reElectNewNaptSwitch : SNAT->Ignoring Re-election for router {} since its not External Router",
160 Routers extRouters = routerData.get();
161 Uuid networkId = extRouters.getNetworkId();
162 if (networkId == null) {
163 LOG.error("hndlTepDelForSnatInEachRtr : SNAT -> Ignoring Re-election with Napt {} for router {}"
164 + "as external network configuraton is missing", primaryNaptDpnId, routerName);
167 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
168 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Router {} is associated with ext nw {}", routerId, networkId);
169 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
171 if (bgpVpnUuid == null) {
172 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Internal VPN-ID {} associated to router {}",
173 routerId, routerName);
176 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
177 if (bgpVpnId == NatConstants.INVALID_ID) {
178 LOG.error("hndlTepDelForSnatInEachRtr :SNAT->Invalid Private BGP VPN ID returned for routerName {}",
183 defaultRouteProgrammer.removeDefNATRouteInDPN(primaryNaptDpnId, bgpVpnId, confTx);
184 if (routerData.get().isEnableSnat()) {
185 LOG.info("hndlTepDelForSnatInEachRtr : SNAT enabled for router {}", routerId);
187 Uint32 routerVpnId = routerId;
188 if (bgpVpnId != NatConstants.INVALID_ID) {
189 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} "
190 + "associated to the router {}", bgpVpnId, routerName);
191 routerVpnId = bgpVpnId;
193 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Internal L3 VPN ID (Router ID) {} "
194 + "associated to the router {}", routerVpnId, routerName);
196 //Re-elect the other available switch as the NAPT switch and program the NAT flows.
197 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
198 routerName, networkId);
199 String externalVpnName = NatUtil.getAssociatedVPN(dataBroker,extRouters.getNetworkId());
200 if (extNwProvType == null) {
203 NatUtil.removeSNATFromDPN(dataBroker, mdsalManager, idManager, naptSwitchHA, primaryNaptDpnId, extRouters,
204 routerId, routerVpnId, externalVpnName, extNwProvType, confTx);
207 LOG.info("hndlTepDelForSnatInEachRtr : SNAT is not enabled for router {} to handle addDPN event {}",
208 routerId, primaryNaptDpnId);