natservice: drop nullToEmpty and reqNonNullOrElse
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / UpgradeStateListener.java
1 /*
2  * Copyright (c) 2017 Red Hat, Inc. and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.netvirt.natservice.internal;
10
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12
13 import com.google.common.base.Optional;
14 import java.math.BigInteger;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.concurrent.ExecutionException;
18 import javax.annotation.Nonnull;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
25 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
26 import org.opendaylight.genius.infra.Datastore.Configuration;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
30 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
31 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
32 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
33 import org.opendaylight.serviceutils.tools.mdsal.listener.AbstractClusteredSyncDataTreeChangeListener;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
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.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 @Singleton
49 public class UpgradeStateListener extends AbstractClusteredSyncDataTreeChangeListener<UpgradeConfig> {
50     private static final Logger LOG = LoggerFactory.getLogger(UpgradeStateListener.class);
51
52     private final DataBroker dataBroker;
53     private final CentralizedSwitchScheduler centralizedSwitchScheduler;
54     private final NatserviceConfig.NatMode natMode;
55     private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
56     private IMdsalApiManager mdsalManager;
57     private IdManagerService idManager;
58     private final NaptSwitchHA naptSwitchHA;
59     private final JobCoordinator coordinator;
60     private final ManagedNewTransactionRunner txRunner;
61
62     @Inject
63     public UpgradeStateListener(final DataBroker dataBroker,
64                                 final CentralizedSwitchScheduler centralizedSwitchScheduler,
65                                 final SNATDefaultRouteProgrammer defaultRouteProgrammer,
66                                 final IMdsalApiManager mdsalManager,
67                                 final IdManagerService idManager,
68                                 final NaptSwitchHA naptSwitchHA,
69                                 final NatserviceConfig config, final JobCoordinator coordinator) {
70         super(dataBroker, new DataTreeIdentifier<>(
71                 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(UpgradeConfig.class)));
72         this.dataBroker = dataBroker;
73         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
74         this.centralizedSwitchScheduler = centralizedSwitchScheduler;
75         this.defaultRouteProgrammer = defaultRouteProgrammer;
76         this.coordinator = coordinator;
77         this.naptSwitchHA = naptSwitchHA;
78         if (config != null) {
79             this.natMode = config.getNatMode();
80         } else {
81             this.natMode = NatserviceConfig.NatMode.Controller;
82         }
83         LOG.trace("UpgradeStateListener (nat) initialized");
84     }
85
86     @Override
87     public void add(@Nonnull UpgradeConfig newDataObject) {
88     }
89
90     @Override
91     public void remove(@Nonnull UpgradeConfig removedDataObject) {
92         if (natMode == NatserviceConfig.NatMode.Conntrack) {
93             return;
94         }
95         LOG.debug("Verify is all Elected Napt Switch and connected back post upgrade");
96     }
97
98     @Override
99     public void update(@Nonnull UpgradeConfig original, UpgradeConfig updated) {
100         if (natMode == NatserviceConfig.NatMode.Controller) {
101             if (original.isUpgradeInProgress() && !updated.isUpgradeInProgress()) {
102                 Optional<NaptSwitches> npatSwitches = NatUtil.getAllPrimaryNaptSwitches(dataBroker);
103                 if (npatSwitches.isPresent()) {
104                     for (RouterToNaptSwitch routerToNaptSwitch : npatSwitches.get().nonnullRouterToNaptSwitch()) {
105                         BigInteger primaryNaptDpnId = routerToNaptSwitch.getPrimarySwitchId();
106                         if (!NatUtil.getSwitchStatus(dataBroker, routerToNaptSwitch.getPrimarySwitchId())) {
107                             String routerUuid = routerToNaptSwitch.getRouterName();
108                             coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerUuid,
109                                 () -> Collections.singletonList(
110                                     txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
111                                         confTx -> reElectNewNaptSwitch(routerUuid, primaryNaptDpnId, confTx)
112                                 )), NatConstants.NAT_DJC_MAX_RETRIES);
113                         }
114                     }
115                 }
116             }
117             return;
118         }
119
120         LOG.info("UpgradeStateListener update from {} to {}", original, updated);
121         if (!(original.isUpgradeInProgress() && !updated.isUpgradeInProgress())) {
122             return;
123         }
124
125         SingleTransactionDataBroker reader = new SingleTransactionDataBroker(dataBroker);
126         ExtRouters routers;
127         try {
128             routers = reader.syncRead(LogicalDatastoreType.CONFIGURATION,
129                     InstanceIdentifier.create(ExtRouters.class));
130         } catch (ReadFailedException e) {
131             LOG.error("Error reading external routers", e);
132             return;
133         }
134
135         for (Routers router : routers.nonnullRouters()) {
136             List<ExternalIps> externalIps = router.getExternalIps();
137             if (router.isEnableSnat() && externalIps != null && !externalIps.isEmpty()) {
138                 centralizedSwitchScheduler.scheduleCentralizedSwitch(router);
139             }
140         }
141     }
142
143     private void reElectNewNaptSwitch(String routerName, BigInteger primaryNaptDpnId,
144             TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
145         // Check if this is externalRouter else ignore
146         InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
147         Optional<Routers> routerData =
148                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
149                         LogicalDatastoreType.CONFIGURATION, extRoutersId);
150         if (!routerData.isPresent()) {
151             LOG.debug("reElectNewNaptSwitch : SNAT->Ignoring Re-election for router {} since its not External Router",
152                     routerName);
153             return;
154         }
155         Uuid networkId = routerData.get().getNetworkId();
156         if (networkId == null) {
157             LOG.error("hndlTepDelForSnatInEachRtr : SNAT -> Ignoring Re-election  with Napt {} for router {}"
158                     + "as external network configuraton is missing", primaryNaptDpnId, routerName);
159             return;
160         }
161         long routerId = NatUtil.getVpnId(dataBroker, routerName);
162         LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Router {} is associated with ext nw {}", routerId, networkId);
163         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
164         Long bgpVpnId;
165         if (bgpVpnUuid == null) {
166             LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Internal VPN-ID {} associated to router {}",
167                     routerId, routerName);
168             bgpVpnId = routerId;
169         } else {
170             bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
171             if (bgpVpnId == NatConstants.INVALID_ID) {
172                 LOG.error("hndlTepDelForSnatInEachRtr :SNAT->Invalid Private BGP VPN ID returned for routerName {}",
173                         routerName);
174                 return;
175             }
176         }
177         defaultRouteProgrammer.removeDefNATRouteInDPN(primaryNaptDpnId, bgpVpnId, confTx);
178         if (routerData.get().isEnableSnat()) {
179             LOG.info("hndlTepDelForSnatInEachRtr : SNAT enabled for router {}", routerId);
180
181             long routerVpnId = routerId;
182             if (bgpVpnId != NatConstants.INVALID_ID) {
183                 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} "
184                         + "associated to the router {}", bgpVpnId, routerName);
185                 routerVpnId = bgpVpnId;
186             } else {
187                 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Internal L3 VPN ID (Router ID) {} "
188                         + "associated to the router {}", routerVpnId, routerName);
189             }
190             //Re-elect the other available switch as the NAPT switch and program the NAT flows.
191             ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
192                     routerName, networkId);
193             if (extNwProvType == null) {
194                 return;
195             }
196             NatUtil.removeSNATFromDPN(dataBroker, mdsalManager, idManager, naptSwitchHA, primaryNaptDpnId, routerName,
197                     routerId, routerVpnId, extNwProvType, confTx);
198
199         } else {
200             LOG.info("hndlTepDelForSnatInEachRtr : SNAT is not enabled for router {} to handle addDPN event {}",
201                     routerId, primaryNaptDpnId);
202         }
203     }
204
205 }