Filter notifications for unwanted interfaces
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / InterfaceStateChangeListener.java
1 /*
2  * Copyright (c) 2015, 2017 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.vpnmanager;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.concurrent.ExecutionException;
16
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
21 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
22 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
23 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class InterfaceStateChangeListener
33     extends AsyncDataTreeChangeListenerBase<Interface, InterfaceStateChangeListener> implements AutoCloseable {
34     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
35     private final DataBroker dataBroker;
36     private final VpnInterfaceManager vpnInterfaceManager;
37
38     public InterfaceStateChangeListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager) {
39         super(Interface.class, InterfaceStateChangeListener.class);
40         this.dataBroker = dataBroker;
41         this.vpnInterfaceManager = vpnInterfaceManager;
42     }
43
44     public void start() {
45         LOG.info("{} start", getClass().getSimpleName());
46         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
47     }
48
49
50     @Override
51     protected InstanceIdentifier<Interface> getWildCardPath() {
52         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
53     }
54
55     @Override
56     protected InterfaceStateChangeListener getDataTreeChangeListener() {
57         return InterfaceStateChangeListener.this;
58     }
59
60
61     @Override
62     // TODO Clean up the exception handling
63     @SuppressWarnings("checkstyle:IllegalCatch")
64     protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
65         try {
66             if (L2vlan.class.equals(intrf.getType())) {
67                 LOG.info("VPN Interface add event - intfName {} from InterfaceStateChangeListener",
68                                 intrf.getName());
69                 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
70                 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
71                     () -> {
72                         WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
73                         WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
74                         WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
75                         List<ListenableFuture<Void>> futures = new ArrayList<>();
76
77                         final String interfaceName = intrf.getName();
78                         LOG.info("Detected interface add event for interface {}", interfaceName);
79
80                         final VpnInterface vpnInterface =
81                                 VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
82                         if (vpnInterface != null) {
83                             LOG.debug("VPN Interface Name {}", vpnInterface);
84                             BigInteger intfDpnId = BigInteger.ZERO;
85                             try {
86                                 intfDpnId = InterfaceUtils.getDpIdFromInterface(intrf);
87                             } catch (Exception e) {
88                                 LOG.error("Unable to retrieve dpnId for interface {}. "
89                                         + "Process vpn interface add failed",intrf.getName(), e);
90                                 return futures;
91                             }
92                             final BigInteger dpnId = intfDpnId;
93                             final int ifIndex = intrf.getIfIndex();
94                             if (!vpnInterfaceManager.isVpnInstanceReady(vpnInterface.getVpnInstanceName())) {
95                                 LOG.info("VPN Interface add event - intfName {} onto vpnName {} "
96                                                 + "running oper-driven, VpnInstance not ready, holding on",
97                                         vpnInterface.getName(), vpnInterface.getVpnInstanceName());
98                                 return futures;
99                             }
100                             LOG.info("VPN Interface add event - intfName {} onto vpnName {} running oper-driven",
101                                     vpnInterface.getName(), vpnInterface.getVpnInstanceName());
102                             vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false,
103                                     writeConfigTxn, writeOperTxn, writeInvTxn, intrf);
104                             ListenableFuture<Void> operFuture = writeOperTxn.submit();
105                             try {
106                                 operFuture.get();
107                             } catch (ExecutionException e) {
108                                 LOG.error("InterfaceStateChange - Exception encountered while submitting"
109                                         + " operational future for addVpnInterface {} : {}",
110                                         vpnInterface.getName(), e);
111                                 return null;
112                             }
113                             futures.add(writeConfigTxn.submit());
114                             futures.add(writeInvTxn.submit());
115                         }
116                         return futures;
117                     });
118             }
119         } catch (Exception e) {
120             LOG.error("Exception caught in Interface {} Operational State Up event", intrf.getName(), e);
121         }
122     }
123
124     @Override
125     // TODO Clean up the exception handling
126     @SuppressWarnings("checkstyle:IllegalCatch")
127     protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
128         final String interfaceName = intrf.getName();
129         BigInteger dpId = BigInteger.ZERO;
130         try {
131             if (L2vlan.class.equals(intrf.getType())) {
132                 LOG.info("VPN Interface remove event - intfName {} from InterfaceStateChangeListener",
133                                 intrf.getName());
134                 try {
135                     dpId = InterfaceUtils.getDpIdFromInterface(intrf);
136                 } catch (Exception e) {
137                     LOG.error("Unable to retrieve dpnId from interface operational data store for interface"
138                             + " {}. Fetching from vpn interface op data store. ", interfaceName, e);
139                 }
140                 final BigInteger inputDpId = dpId;
141                 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
142                 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
143                     () -> {
144                         WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
145                         WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
146                         WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
147                         List<ListenableFuture<Void>> futures = new ArrayList<>();
148
149                         InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
150                         Optional<VpnInterface> optVpnInterface =
151                                 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
152                         if (optVpnInterface.isPresent()) {
153                             final VpnInterface vpnInterface = optVpnInterface.get();
154                             BigInteger dpnId = inputDpId;
155                             if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
156                                 dpnId = vpnInterface.getDpnId();
157                             }
158                             final int ifIndex = intrf.getIfIndex();
159                             LOG.info("VPN Interface remove event - intfName {} onto vpnName {} running oper-driven",
160                                     vpnInterface.getName(), vpnInterface.getVpnInstanceName());
161                             vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, intrf,
162                                     vpnInterface, false, writeConfigTxn, writeOperTxn, writeInvTxn);
163                             ListenableFuture<Void> operFuture = writeOperTxn.submit();
164                             try {
165                                 operFuture.get();
166                             } catch (ExecutionException e) {
167                                 LOG.error("InterfaceStateChange - Exception encountered while submitting operational"
168                                         + " future for removeVpnInterface {} : {}", vpnInterface.getName(), e);
169                                 return null;
170                             }
171                             futures.add(writeConfigTxn.submit());
172                             futures.add(writeInvTxn.submit());
173                         } else {
174                             LOG.debug("Interface {} is not a vpninterface, ignoring.", interfaceName);
175                         }
176
177                         return futures;
178                     });
179             }
180         } catch (Exception e) {
181             LOG.error("Exception observed in handling deletion of VPN Interface {}. ", interfaceName, e);
182         }
183     }
184
185     // TODO Clean up the exception handling
186     @SuppressWarnings("checkstyle:IllegalCatch")
187     @Override
188     protected void update(InstanceIdentifier<Interface> identifier,
189                     Interface original, Interface update) {
190         final String interfaceName = update.getName();
191         try {
192             OperStatus originalOperStatus = original.getOperStatus();
193             OperStatus updateOperStatus = update.getOperStatus();
194             if (originalOperStatus.equals(Interface.OperStatus.Unknown)
195                   || updateOperStatus.equals(Interface.OperStatus.Unknown)) {
196                 LOG.debug("Interface {} state change is from/to null/UNKNOWN. Ignoring the update event.",
197                         interfaceName);
198                 return;
199             }
200
201             if (update.getIfIndex() == null) {
202                 return;
203             }
204             if (L2vlan.class.equals(update.getType())) {
205                 LOG.info("VPN Interface update event - intfName {} from InterfaceStateChangeListener",
206                         update.getName());
207                 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
208                 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
209                     () -> {
210                         WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
211                         WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
212                         WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
213                         List<ListenableFuture<Void>> futures = new ArrayList<>();
214                         final VpnInterface vpnInterface =
215                                 VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
216                         if (vpnInterface != null) {
217                             final int ifIndex = update.getIfIndex();
218                             final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
219                             if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
220                                 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running "
221                                         + " oper-driven UP", vpnInterface.getName(),
222                                         vpnInterface.getVpnInstanceName());
223                                 if (!vpnInterfaceManager.isVpnInstanceReady(vpnInterface.getVpnInstanceName())) {
224                                     LOG.info("VPN Interface update event - intfName {} onto vpnName {} "
225                                                     + "running oper-driven UP, VpnInstance not ready, holding on",
226                                             vpnInterface.getName(), vpnInterface.getVpnInstanceName());
227                                     return futures;
228                                 }
229                                 vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex,
230                                         true, writeConfigTxn, writeOperTxn, writeInvTxn, update);
231                             } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
232                                 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running oper-driven"
233                                         + " DOWN", vpnInterface.getName(), vpnInterface.getVpnInstanceName());
234                                 InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
235                                 Optional<VpnInterface> optVpnInterface =
236                                         VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
237                                 if (optVpnInterface.isPresent()) {
238                                     VpnInterface vpnOpInterface = optVpnInterface.get();
239                                     vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, update,
240                                             vpnOpInterface, true, writeConfigTxn, writeOperTxn,
241                                             writeInvTxn);
242                                 } else {
243                                     LOG.error("InterfaceStateChangeListener Update DOWN - vpnInterface {}"
244                                             + " not available, ignoring event", vpnInterface.getName());
245                                     return futures;
246                                 }
247                             }
248                             ListenableFuture<Void> operFuture = writeOperTxn.submit();
249                             try {
250                                 operFuture.get();
251                             } catch (ExecutionException e) {
252                                 LOG.error("InterfaceStateChange - Exception encountered while submitting operational"
253                                         + " future for updateVpnInterface {} : {}", vpnInterface.getName(), e);
254                                 return null;
255                             }
256                             futures.add(writeConfigTxn.submit());
257                             futures.add(writeInvTxn.submit());
258                         } else {
259                             LOG.debug("Interface {} is not a vpninterface, ignoring.", interfaceName);
260                         }
261
262                         return futures;
263                     });
264             }
265         } catch (Exception e) {
266             LOG.error("Exception observed in handling updation of VPN Interface {}. ", update.getName(), e);
267         }
268     }
269 }