2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.genius.interfacemanager.listeners;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.List;
13 import java.util.concurrent.Callable;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
19 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
20 import org.opendaylight.genius.interfacemanager.IfmConstants;
21 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
22 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
23 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
24 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
25 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
26 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
27 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * This class listens for interface creation/removal/update in Configuration DS.
39 * This is used to handle interfaces for base of-ports.
42 public class InterfaceConfigListener
43 extends AsyncClusteredDataTreeChangeListenerBase<Interface, InterfaceConfigListener> {
44 private static final Logger LOG = LoggerFactory.getLogger(InterfaceConfigListener.class);
45 private final DataBroker dataBroker;
46 private final IdManagerService idManager;
47 private final AlivenessMonitorService alivenessMonitorService;
48 private final IMdsalApiManager mdsalApiManager;
49 private final InterfacemgrProvider interfaceMgrProvider;
52 public InterfaceConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
53 final IMdsalApiManager mdsalApiManager, final InterfacemgrProvider interfaceMgrProvider,
54 final AlivenessMonitorService alivenessMonitorService) {
55 super(Interface.class, InterfaceConfigListener.class);
56 this.dataBroker = dataBroker;
57 this.idManager = idManager;
58 this.mdsalApiManager = mdsalApiManager;
59 this.interfaceMgrProvider = interfaceMgrProvider;
60 this.alivenessMonitorService = alivenessMonitorService;
61 this.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
65 protected InstanceIdentifier<Interface> getWildCardPath() {
66 return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
70 protected InterfaceConfigListener getDataTreeChangeListener() {
71 return InterfaceConfigListener.this;
74 private void updateInterfaceParentRefs(Interface iface) {
75 String ifName = iface.getName();
76 // try to acquire the parent interface name from Southbound
77 String parentRefName = interfaceMgrProvider.getParentRefNameForInterface(ifName);
78 if (parentRefName == null) {
79 LOG.debug("parent refs not specified for {}, failed acquiring it from southbound", ifName);
82 LOG.debug("retrieved parent ref {} for interface {} from southbound, updating parentRef in datastore",
83 parentRefName, ifName);
84 interfaceMgrProvider.updateInterfaceParentRef(ifName, parentRefName, false);
89 protected void remove(InstanceIdentifier<Interface> key, Interface interfaceOld) {
90 IfmClusterUtils.runOnlyInLeaderNode(() -> {
91 LOG.debug("Received Interface Remove Event: {}, {}", key, interfaceOld);
92 String ifName = interfaceOld.getName();
93 ParentRefs parentRefs = interfaceOld.getAugmentation(ParentRefs.class);
94 if (parentRefs == null
95 || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
96 LOG.warn("parent refs not specified for {}", interfaceOld.getName());
99 boolean isTunnelInterface = InterfaceManagerCommonUtils.isTunnelInterface(interfaceOld);
100 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
101 RendererConfigRemoveWorker configWorker = new RendererConfigRemoveWorker(key, interfaceOld,
102 interfaceOld.getName(), parentRefs);
103 String synchronizationKey = isTunnelInterface ? parentRefs.getDatapathNodeIdentifier().toString()
104 : parentRefs.getParentInterface();
105 coordinator.enqueueJob(synchronizationKey, configWorker, IfmConstants.JOB_MAX_RETRIES);
106 }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
110 protected void update(InstanceIdentifier<Interface> key, Interface interfaceOld, Interface interfaceNew) {
111 IfmClusterUtils.runOnlyInLeaderNode(() -> {
112 LOG.debug("Received Interface Update Event: {}, {}, {}", key, interfaceOld, interfaceNew);
113 ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
114 if (parentRefs == null || parentRefs.getParentInterface() == null) {
115 // If parentRefs are missing, try to find a matching parent and
116 // update - this will trigger another DCN
117 updateInterfaceParentRefs(interfaceNew);
120 String ifNameNew = interfaceNew.getName();
121 if (parentRefs == null
122 || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
123 LOG.debug("parent refs not specified for {}, or parentRefs {} missing DPN/parentInterface",
124 interfaceNew.getName(), parentRefs);
127 boolean isTunnelInterface = InterfaceManagerCommonUtils.isTunnelInterface(interfaceOld);
128 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
129 RendererConfigUpdateWorker configWorker = new RendererConfigUpdateWorker(key, interfaceOld, interfaceNew,
130 interfaceNew.getName());
131 String synchronizationKey = isTunnelInterface ? interfaceOld.getName() : parentRefs.getParentInterface();
132 coordinator.enqueueJob(synchronizationKey, configWorker, IfmConstants.JOB_MAX_RETRIES);
134 }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
138 protected void add(InstanceIdentifier<Interface> key, Interface interfaceNew) {
139 IfmClusterUtils.runOnlyInLeaderNode(() -> {
140 LOG.debug("Received Interface Add Event: {}, {}", key, interfaceNew);
141 ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
142 if (parentRefs == null || parentRefs.getParentInterface() == null) {
143 // If parentRefs are missing, try to find a matching parent and
144 // update - this will trigger another DCN
145 updateInterfaceParentRefs(interfaceNew);
148 String ifName = interfaceNew.getName();
149 if (parentRefs == null
150 || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
151 LOG.warn("parent refs not specified for {}", interfaceNew.getName());
154 boolean isTunnelInterface = InterfaceManagerCommonUtils.isTunnelInterface(interfaceNew);
155 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
156 RendererConfigAddWorker configWorker = new RendererConfigAddWorker(key, interfaceNew, parentRefs,
157 interfaceNew.getName());
158 String synchronizationKey = isTunnelInterface ? interfaceNew.getName() : parentRefs.getParentInterface();
159 coordinator.enqueueJob(synchronizationKey, configWorker, IfmConstants.JOB_MAX_RETRIES);
160 }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
163 private class RendererConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
164 InstanceIdentifier<Interface> key;
165 Interface interfaceNew;
167 ParentRefs parentRefs;
169 RendererConfigAddWorker(InstanceIdentifier<Interface> key, Interface interfaceNew, ParentRefs parentRefs,
172 this.interfaceNew = interfaceNew;
173 this.portName = portName;
174 this.parentRefs = parentRefs;
178 public List<ListenableFuture<Void>> call() {
179 // If another renderer(for eg : CSS) needs to be supported, check
180 // can be performed here
181 // to call the respective helpers.
182 return OvsInterfaceConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew, idManager,
183 alivenessMonitorService, mdsalApiManager);
187 public String toString() {
188 return "RendererConfigAddWorker{" + "key=" + key + ", interfaceNew=" + interfaceNew + ", portName='"
189 + portName + '\'' + '}';
193 private class RendererConfigUpdateWorker implements Callable {
194 InstanceIdentifier<Interface> key;
195 Interface interfaceOld;
196 Interface interfaceNew;
199 RendererConfigUpdateWorker(InstanceIdentifier<Interface> key, Interface interfaceOld,
200 Interface interfaceNew, String portNameNew) {
202 this.interfaceOld = interfaceOld;
203 this.interfaceNew = interfaceNew;
204 this.portNameNew = portNameNew;
208 public List<ListenableFuture<Void>> call() {
209 // If another renderer(for eg : CSS) needs to be supported, check
210 // can be performed here
211 // to call the respective helpers.
212 return OvsInterfaceConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager,
213 mdsalApiManager, interfaceNew, interfaceOld);
217 public String toString() {
218 return "RendererConfigUpdateWorker{" + "key=" + key + ", interfaceOld=" + interfaceOld + ", interfaceNew="
219 + interfaceNew + ", portNameNew='" + portNameNew + '\'' + '}';
223 private class RendererConfigRemoveWorker implements Callable {
224 InstanceIdentifier<Interface> key;
225 Interface interfaceOld;
227 ParentRefs parentRefs;
229 RendererConfigRemoveWorker(InstanceIdentifier<Interface> key, Interface interfaceOld, String portName,
230 ParentRefs parentRefs) {
232 this.interfaceOld = interfaceOld;
233 this.portName = portName;
234 this.parentRefs = parentRefs;
238 public List<ListenableFuture<Void>> call() {
239 // If another renderer(for eg : CSS) needs to be supported, check
240 // can be performed here
241 // to call the respective helpers.
242 return OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService, interfaceOld,
243 idManager, mdsalApiManager, parentRefs);
247 public String toString() {
248 return "RendererConfigRemoveWorker{" + "key=" + key + ", interfaceOld=" + interfaceOld + ", portName='"
249 + portName + '\'' + '}';