MRI version bump for Aluminium
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / TerminationPointStateListener.java
1 /*
2  * Copyright (c) 2016, 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.genius.interfacemanager.listeners;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.util.List;
12 import java.util.concurrent.Callable;
13 import javax.inject.Inject;
14 import javax.inject.Singleton;
15 import org.apache.aries.blueprint.annotation.service.Reference;
16 import org.opendaylight.genius.interfacemanager.IfmConstants;
17 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
18 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
19 import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
20 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
21 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
22 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
23 import org.opendaylight.infrautils.utils.concurrent.Executors;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
27 import org.opendaylight.serviceutils.srm.RecoverableListener;
28 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
29 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 @Singleton
40 public class TerminationPointStateListener extends
41         AbstractClusteredAsyncDataTreeChangeListener<OvsdbTerminationPointAugmentation>
42         implements RecoverableListener {
43     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointStateListener.class);
44     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
45
46     private final InterfacemgrProvider interfaceMgrProvider;
47     private final DataBroker dataBroker;
48     private final EntityOwnershipUtils entityOwnershipUtils;
49     private final JobCoordinator coordinator;
50     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
51     private final OvsInterfaceTopologyStateUpdateHelper ovsInterfaceTopologyStateUpdateHelper;
52
53     @Inject
54     public TerminationPointStateListener(@Reference final DataBroker dataBroker,
55                                          final InterfacemgrProvider interfaceMgrProvider,
56                                          final EntityOwnershipUtils entityOwnershipUtils,
57                                          @Reference final JobCoordinator coordinator,
58                                          final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
59                                          final OvsInterfaceTopologyStateUpdateHelper
60                                                      ovsInterfaceTopologyStateUpdateHelper,
61                                          final InterfaceServiceRecoveryHandler interfaceServiceRecoveryHandler,
62                                          @Reference final ServiceRecoveryRegistry serviceRecoveryRegistry) {
63         super(dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class)
64                         .child(Topology.class).child(Node.class)
65                         .child(TerminationPoint.class).augmentation(OvsdbTerminationPointAugmentation.class).build(),
66                 Executors.newSingleThreadExecutor("TerminationPointStateListener", LOG));
67         this.interfaceMgrProvider = interfaceMgrProvider;
68         this.entityOwnershipUtils = entityOwnershipUtils;
69         this.coordinator = coordinator;
70         this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
71         this.ovsInterfaceTopologyStateUpdateHelper = ovsInterfaceTopologyStateUpdateHelper;
72         this.dataBroker = dataBroker;
73         serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(),
74                 this);
75     }
76
77     @Override
78     public void registerListener() {
79         super.register();
80     }
81
82     @Override
83     public void deregisterListener() {
84         close();
85     }
86
87     @Override
88     public void remove(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
89                           OvsdbTerminationPointAugmentation tpOld) {
90         // No ItmDirectTunnels or Internal Tunnel checking is done here as this DTCN only results in removal
91         // of interface entry from BFD internal cache. For internal tunnels when ItmDirectTunnel is enabled,
92         // the entry won't be in cache, but ConcurrentHashMap will just ignore when key is not present.
93
94         LOG.debug("Received remove DataChange Notification for ovsdb termination point {}", tpOld.getName());
95
96         String oldInterfaceName = SouthboundUtils.getExternalInterfaceIdValue(tpOld);
97         if (oldInterfaceName == null && InterfaceManagerCommonUtils.isTunnelPort(tpOld.getName())) {
98             interfaceMgrProvider.removeTerminationPointForInterface(tpOld.getName());
99             interfaceMgrProvider.removeNodeIidForInterface(tpOld.getName());
100         } else {
101             interfaceMgrProvider.removeTerminationPointForInterface(oldInterfaceName);
102             interfaceMgrProvider.removeNodeIidForInterface(oldInterfaceName);
103         }
104         if (tpOld.getInterfaceBfdStatus() != null) {
105             LOG.debug("Received termination point removed notification with bfd status values {}", tpOld.getName());
106             EVENT_LOGGER.debug("IFM-TerminationPointState,REMOVE {}", tpOld.getName());
107             RendererStateRemoveWorker rendererStateRemoveWorker = new RendererStateRemoveWorker(tpOld);
108             coordinator.enqueueJob(tpOld.getName(), rendererStateRemoveWorker);
109         }
110     }
111
112     @Override
113     public void update(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
114                           OvsdbTerminationPointAugmentation tpOld,
115                           OvsdbTerminationPointAugmentation tpNew) {
116         if (interfaceMgrProvider.isItmDirectTunnelsEnabled()
117             && InterfaceManagerCommonUtils.isTunnelPort(tpNew.getName())
118             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(tpNew.getName()) == null) {
119             LOG.debug("ITM Direct Tunnels is enabled, hence ignoring termination point update - "
120                     + "old {}, new {} internal tunnel", tpOld.getName(), tpNew.getName());
121             return;
122         }
123
124
125         LOG.debug("Received Update DataChange Notification for ovsdb termination point {}", tpNew.getName());
126         EVENT_LOGGER.debug("IFM-TerminationPointState,UPDATE {}", tpNew.getName());
127         if (org.opendaylight.genius.interfacemanager.renderer.ovs.utilities
128                 .SouthboundUtils.changeInBfdMonitoringDetected(tpOld, tpNew)
129                 || org.opendaylight.genius.interfacemanager.renderer.ovs.utilities
130                 .SouthboundUtils.ifBfdStatusNotEqual(tpOld, tpNew)) {
131             LOG.info("Bfd Status changed for ovsdb termination point {}", tpNew.getName());
132             LOG.debug("Bfd Status changed for ovsdb termination point identifier: {},  old: {}, new: {}",
133                     identifier, tpOld, tpNew);
134             RendererStateUpdateWorker rendererStateAddWorker = new RendererStateUpdateWorker(tpNew);
135             coordinator.enqueueJob(tpNew.getName(), rendererStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
136         }
137
138         InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
139         String newInterfaceName = SouthboundUtils.getExternalInterfaceIdValue(tpNew);
140         if (newInterfaceName == null && InterfaceManagerCommonUtils.isTunnelPort(tpNew.getName())) {
141             interfaceMgrProvider.addTerminationPointForInterface(tpNew.getName(), tpNew);
142             interfaceMgrProvider.addNodeIidForInterface(tpNew.getName(), nodeIid);
143         } else {
144             interfaceMgrProvider.addTerminationPointForInterface(newInterfaceName, tpNew);
145             interfaceMgrProvider.addNodeIidForInterface(newInterfaceName, nodeIid);
146         }
147
148         // skip parent-refs updation for interfaces with external-id for tunnels
149         if (!org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils.isInterfaceTypeTunnel(
150             tpNew.getInterfaceType())) {
151             if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
152                     IfmConstants.INTERFACE_CONFIG_ENTITY)) {
153                 return;
154             }
155             String dpnId = interfaceMgrProvider.getDpidForInterface(newInterfaceName, nodeIid);
156             String oldInterfaceName = SouthboundUtils.getExternalInterfaceIdValue(tpOld);
157             if (dpnId != null && newInterfaceName != null && (oldInterfaceName == null
158                 || !oldInterfaceName.equals(newInterfaceName))) {
159                 String parentRefName =
160                         InterfaceManagerCommonUtils.getPortNameForInterface(dpnId, tpNew.getName());
161                 LOG.debug("Detected update to termination point {} with external ID {}, updating parent ref "
162                     + "of that interface ID to this termination point's interface-state name {}", tpNew.getName(),
163                     newInterfaceName, parentRefName);
164                 interfaceMgrProvider.updateInterfaceParentRef(newInterfaceName, parentRefName);
165             }
166         }
167     }
168
169     @Override
170     public void add(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
171                        OvsdbTerminationPointAugmentation tpNew) {
172         if (interfaceMgrProvider.isItmDirectTunnelsEnabled()
173             && InterfaceManagerCommonUtils.isTunnelPort(tpNew.getName())
174             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(tpNew.getName()) == null) {
175             LOG.debug("ITM Direct Tunnels is enabled, hence ignoring termination point add for"
176                     + " internal tunnel {}", tpNew.getName());
177             return;
178         }
179         update(identifier, null, tpNew);
180     }
181
182     private class RendererStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
183         OvsdbTerminationPointAugmentation terminationPointNew;
184
185         RendererStateUpdateWorker(OvsdbTerminationPointAugmentation tpNew) {
186             this.terminationPointNew = tpNew;
187         }
188
189         @Override
190         public List<ListenableFuture<Void>> call() {
191             return ovsInterfaceTopologyStateUpdateHelper.updateTunnelState(terminationPointNew);
192         }
193     }
194
195     private class RendererStateRemoveWorker implements Callable<List<? extends ListenableFuture<?>>> {
196         OvsdbTerminationPointAugmentation terminationPointOld;
197
198         RendererStateRemoveWorker(OvsdbTerminationPointAugmentation tpNew) {
199             this.terminationPointOld = tpNew;
200         }
201
202         @Override
203         public List<ListenableFuture<Void>> call() {
204             LOG.debug("Removing bfd state from cache, if any, for {}", terminationPointOld.getName());
205             interfaceManagerCommonUtils.removeBfdStateFromCache(terminationPointOld.getName());
206             return null;
207         }
208     }
209 }