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