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