Migrate ListenableFutures.addErrorLogging() users
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatRouterInterfaceListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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 package org.opendaylight.netvirt.natservice.internal;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import java.util.concurrent.locks.ReentrantLock;
14 import javax.annotation.PreDestroy;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
18 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
19 import org.opendaylight.genius.mdsalutil.MDSALUtil;
20 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
21 import org.opendaylight.infrautils.utils.concurrent.Executors;
22 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
25 import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.opendaylight.yangtools.yang.common.Uint64;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 @Singleton
40 public class NatRouterInterfaceListener extends AbstractAsyncDataTreeChangeListener<Interfaces> {
41
42     private static final Logger LOG = LoggerFactory.getLogger(NatRouterInterfaceListener.class);
43     private final DataBroker dataBroker;
44     private final ManagedNewTransactionRunner txRunner;
45     private final OdlInterfaceRpcService interfaceManager;
46     private final IMdsalApiManager mdsalManager;
47     private final NaptManager naptManager;
48     private final NeutronvpnService neutronVpnService;
49
50     @Inject
51     public NatRouterInterfaceListener(final DataBroker dataBroker, final OdlInterfaceRpcService interfaceManager,
52         final IMdsalApiManager mdsalManager,final NaptManager naptManager,
53         final NeutronvpnService neutronvpnService) {
54         super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(RouterInterfacesMap.class)
55                 .child(RouterInterfaces.class).child(Interfaces.class),
56                 Executors.newListeningSingleThreadExecutor("NatRouterInterfaceListener", LOG));
57         this.dataBroker = dataBroker;
58         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
59         this.interfaceManager = interfaceManager;
60         this.mdsalManager = mdsalManager;
61         this.naptManager = naptManager;
62         this.neutronVpnService = neutronvpnService;
63     }
64
65     public void init() {
66         LOG.info("{} init", getClass().getSimpleName());
67     }
68
69     @Override
70     @PreDestroy
71     public void close() {
72         super.close();
73         Executors.shutdownAndAwaitTermination(getExecutorService());
74     }
75
76     @Override
77     // TODO Clean up the exception handling
78     @SuppressWarnings("checkstyle:IllegalCatch")
79     public void add(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {
80         LOG.trace("add : Add event - key: {}, value: {}", interfaceInfo.key(), interfaceInfo);
81         final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();
82         final String interfaceName = interfaceInfo.getInterfaceId();
83         if (NatUtil.isRouterInterfacePort(dataBroker, interfaceName)) {
84             LOG.info("ADD: Ignoring Router Interface Port {} for processing of router {}", interfaceName, routerId);
85             return;
86         }
87         try {
88             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
89                 NatUtil.getRouterInterfaceId(interfaceName), getRouterInterface(interfaceName, routerId));
90         } catch (Exception e) {
91             LOG.error("add: Unable to write data in RouterInterface model", e);
92         }
93
94         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
95             .state.Interface interfaceState = NatUtil.getInterfaceStateFromOperDS(dataBroker, interfaceName);
96         if (interfaceState != null) {
97             Uint64 dpId = NatUtil.getDpIdFromInterface(interfaceState);
98             if (dpId.equals(Uint64.ZERO)) {
99                 LOG.warn("ADD : Could not retrieve dp id for interface {} to handle router {} association model",
100                         interfaceName, routerId);
101                 return;
102             }
103             final ReentrantLock lock = NatUtil.lockForNat(dpId);
104             lock.lock();
105             try {
106                 LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL,
107                     operTx -> {
108                         NatUtil.addToNeutronRouterDpnsMap(routerId, interfaceName, dpId, operTx);
109                         NatUtil.addToDpnRoutersMap(routerId, interfaceName, dpId, operTx);
110                     }), LOG, "Error processing NAT router interface addition");
111             } finally {
112                 lock.unlock();
113             }
114             LOG.info("ADD: Added neutron-router-dpns mapping for interface {} of router {}", interfaceName, routerId);
115         } else {
116             LOG.info("add : Interface {} not yet operational to handle router interface add event in router {}",
117                     interfaceName, routerId);
118         }
119     }
120
121     @Override
122     public void remove(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {
123         LOG.trace("remove : Remove event - key: {}, value: {}", interfaceInfo.key(), interfaceInfo);
124         final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();
125         final String interfaceName = interfaceInfo.getInterfaceId();
126         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
127             interfaceState = NatUtil.getInterfaceStateFromOperDS(dataBroker, interfaceName);
128         if (interfaceState != null) {
129             Uint64 dpId = NatUtil.getDpIdFromInterface(interfaceState);
130             if (dpId.equals(Uint64.ZERO)) {
131                 LOG.warn(
132                     "REMOVE : Could not retrieve DPN ID for interface {} to handle router {} dissociation model",
133                     interfaceName, routerId);
134                 return;
135             }
136
137             final ReentrantLock lock = NatUtil.lockForNat(dpId);
138             lock.lock();
139             try {
140                 if (NatUtil.isSnatEnabledForRouterId(dataBroker, routerId)) {
141                     NatUtil.removeSnatEntriesForPort(dataBroker, naptManager, mdsalManager, neutronVpnService,
142                         interfaceName, routerId);
143                 }
144                 LoggingFutures.addErrorLogging(
145                     txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
146                         //Delete the NeutronRouterDpnMap from the ODL:L3VPN operational model
147                         NatUtil
148                             .removeFromNeutronRouterDpnsMap(routerId, interfaceName, dpId, operTx);
149                         //Delete the DpnRouterMap from the ODL:L3VPN operational model
150                         NatUtil.removeFromDpnRoutersMap(dataBroker, routerId, interfaceName, dpId,
151                             interfaceManager, operTx);
152                     }), LOG, "Error handling NAT router interface removal");
153                 //Delete the RouterInterfaces maintained in the ODL:L3VPN configuration model
154                 LoggingFutures.addErrorLogging(
155                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
156                         confTx -> confTx.delete(NatUtil.getRouterInterfaceId(interfaceName))), LOG,
157                         "Error handling NAT router interface removal");
158             } finally {
159                 lock.unlock();
160             }
161         }
162     }
163
164     @Override
165     public void update(InstanceIdentifier<Interfaces> identifier, Interfaces original, Interfaces update) {
166         LOG.trace("update key: {}, original: {}, update: {}", update.key(), original, update);
167     }
168
169     static RouterInterface getRouterInterface(String interfaceName, String routerName) {
170         return new RouterInterfaceBuilder().withKey(new RouterInterfaceKey(interfaceName))
171             .setInterfaceName(interfaceName).setRouterName(routerName).build();
172     }
173 }
174