Merge "IPv6Service Binding using elanTag"
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / InterfaceStateChangeListener.java
1 /*
2  * Copyright (c) 2015 - 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.vpnmanager;
9
10 import com.google.common.base.Optional;
11
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
21 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
22 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
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.neutron.ports.rev150712.ports.attributes.Ports;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
31 import org.opendaylight.yangtools.concepts.ListenerRegistration;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import java.math.BigInteger;
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.concurrent.Callable;
40 import java.util.concurrent.ExecutionException;
41
42 public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
43     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
44     private ListenerRegistration<DataChangeListener> listenerRegistration;
45     private final DataBroker dataBroker;
46     private final VpnInterfaceManager vpnInterfaceManager;
47
48     public InterfaceStateChangeListener(final DataBroker dataBroker, VpnInterfaceManager vpnInterfaceManager) {
49         super(Interface.class);
50         this.dataBroker = dataBroker;
51         this.vpnInterfaceManager = vpnInterfaceManager;
52     }
53
54     public void start() {
55         LOG.info("{} start", getClass().getSimpleName());
56         listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
57                 getWildCardPath(), this, DataChangeScope.SUBTREE);
58     }
59
60     private InstanceIdentifier<Interface> getWildCardPath() {
61         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
62     }
63
64     @Override
65     public void close() throws Exception {
66         if (listenerRegistration != null) {
67             listenerRegistration.close();
68             listenerRegistration = null;
69         }
70         LOG.info("{} close", getClass().getSimpleName());
71     }
72
73     @Override
74     protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
75         LOG.trace("Received interface {} add event", intrf);
76         LOG.info("Received interface {} add event", intrf.getName());
77         try {
78             final String interfaceName = intrf.getName();
79             LOG.info("Received interface add event for interface {} ", interfaceName);
80             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
81                     configInterface = InterfaceUtils.getInterface(dataBroker, interfaceName);
82             if (configInterface != null) {
83                 if (!configInterface.getType().equals(Tunnel.class)) {
84                     // We service only VM interfaces and Router interfaces here.
85                     // We donot service Tunnel Interfaces here.
86                     // Tunnel events are directly serviced
87                     // by TunnelInterfacesStateListener present as part of VpnInterfaceManager
88                     LOG.debug("Config Interface Name {}", configInterface.getName());
89                     final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
90                     if (vpnInterface != null) {
91                         LOG.debug("VPN Interface Name {}", vpnInterface);
92                         final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
93                         final int ifIndex = intrf.getIfIndex();
94                         DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
95                         dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
96                                 new Callable<List<ListenableFuture<Void>>>() {
97                                     @Override
98                                     public List<ListenableFuture<Void>> call() throws Exception {
99                                         WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
100                                         WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
101                                         WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
102                                         vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false,
103                                                 writeConfigTxn, writeOperTxn, writeInvTxn);
104                                         String routerName = VpnUtil.getNeutronRouterFromInterface(dataBroker, interfaceName);
105                                         if (routerName != null) {
106                                             LOG.debug("Router Name {} ", routerName);
107                                             handleRouterInterfacesUpEvent(routerName, interfaceName, writeOperTxn);
108                                         } else {
109                                             LOG.info("Unable to process add for interface {} for NAT service", interfaceName);
110                                         }
111                                         List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
112                                         futures.add(writeOperTxn.submit());
113                                         futures.add(writeConfigTxn.submit());
114                                         futures.add(writeInvTxn.submit());
115                                         return futures;
116                                     }
117                                 });
118                     }
119                 }
120             } else {
121                 LOG.error("Unable to process add for interface {} ," +
122                         "since Interface ConfigDS entry absent for the same", interfaceName);
123             }
124         } catch (Exception e) {
125           LOG.error("Exception caught in Interface Operational State Up event", e);
126         }
127     }
128
129     @Override
130     protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
131         LOG.trace("Received interface {} down event", intrf);
132         LOG.info("Received interface {} remove event", intrf.getName());
133         try {
134             final String interfaceName = intrf.getName();
135             LOG.info("Received port DOWN event for interface {} ", interfaceName);
136             if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
137                 //withdraw all prefixes in all vpns for this dpn from bgp
138                 // FIXME: Blocked until tunnel event[vxlan/gre] support is available
139                 // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
140             } else {
141                 BigInteger dpId = BigInteger.ZERO;
142                 InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
143                 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
144                 if (!optVpnInterface.isPresent()) {
145                     LOG.debug("Interface {} is not a vpninterface, ignoring.", intrf.getName());
146                     return;
147                 }
148                 final VpnInterface vpnInterface = optVpnInterface.get();
149                 try {
150                     dpId = InterfaceUtils.getDpIdFromInterface(intrf);
151                 } catch (Exception e){
152                     LOG.warn("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
153                     dpId = vpnInterface.getDpnId();
154                 }
155                 final BigInteger dpnId = dpId;
156                 final int ifIndex = intrf.getIfIndex();
157                 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
158                 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
159                         new Callable<List<ListenableFuture<Void>>>() {
160                             @Override
161                             public List<ListenableFuture<Void>> call() throws Exception {
162                                 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
163                                 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
164                                 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
165                                 vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, false, false,
166                                         writeConfigTxn, writeOperTxn, writeInvTxn);
167                                 RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
168                                 if (routerInterface != null) {
169                                     handleRouterInterfacesDownEvent(routerInterface.getRouterName(), interfaceName, dpnId, writeOperTxn);
170                                 }
171                                 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
172                                 futures.add(writeOperTxn.submit());
173                                 futures.add(writeConfigTxn.submit());
174                                 futures.add(writeInvTxn.submit());
175                                 return futures;
176                             }
177                         });
178             }
179         } catch (Exception e) {
180             LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
181         }
182     }
183
184     @Override
185     protected void update(InstanceIdentifier<Interface> identifier,
186                           Interface original, Interface update) {
187         LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
188         final String interfaceName = update.getName();
189         if (original.getOperStatus().equals(Interface.OperStatus.Unknown) ||
190                 update.getOperStatus().equals(Interface.OperStatus.Unknown)){
191             LOG.debug("Interface {} state change is from/to UNKNOWN. Ignoring the update event.", interfaceName);
192             return;
193         }
194         final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
195         final int ifIndex = update.getIfIndex();
196         if (update != null) {
197             if (!update.getType().equals(Tunnel.class)) {
198                 final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
199                 if (vpnInterface != null) {
200                     if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
201                         DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
202                         dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
203                                 new Callable<List<ListenableFuture<Void>>>() {
204                                     @Override
205                                     public List<ListenableFuture<Void>> call() throws Exception {
206                                         WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
207                                         WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
208                                         WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
209                                         vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, 
210                                                 true, writeConfigTxn, writeOperTxn, writeInvTxn);
211                                         List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
212                                         futures.add(writeOperTxn.submit());
213                                         futures.add(writeConfigTxn.submit());
214                                         futures.add(writeInvTxn.submit());
215                                         return futures;
216                                     }
217                                 });
218                     } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
219                         DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
220                         dataStoreCoordinator.enqueueJob(interfaceName,
221                                 new Callable<List<ListenableFuture<Void>>>() {
222                                     @Override
223                                     public List<ListenableFuture<Void>> call() throws Exception {
224                                         WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
225                                         WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
226                                         WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
227                                         vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, true, false,
228                                                 writeConfigTxn, writeOperTxn, writeInvTxn);
229                                         List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
230                                         futures.add(writeOperTxn.submit());
231                                         futures.add(writeConfigTxn.submit());
232                                         futures.add(writeInvTxn.submit());
233                                         return futures;
234                                     }
235                                 });
236                     }
237                 }
238             }
239         }
240     }
241
242     void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeOperTxn) {
243         LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
244         vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName, writeOperTxn);
245     }
246
247     void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId,
248                                          WriteTransaction writeOperTxn) {
249         LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
250         vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName, dpnId, writeOperTxn);
251     }
252
253 }