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
8 package org.opendaylight.genius.interfacemanager.listeners;
10 import com.google.common.util.concurrent.ListenableFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import java.util.concurrent.Callable;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
24 import org.opendaylight.genius.interfacemanager.IfmConstants;
25 import org.opendaylight.genius.interfacemanager.IfmUtil;
26 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
27 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
28 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
29 import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
30 import org.opendaylight.genius.interfacemanager.recovery.listeners.RecoverableListener;
31 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
32 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
33 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
34 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
47 public class InterfaceTopologyStateListener
48 extends AsyncClusteredDataTreeChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener>
49 implements RecoverableListener {
50 private static final Logger LOG = LoggerFactory.getLogger(InterfaceTopologyStateListener.class);
51 private final DataBroker dataBroker;
52 private final InterfacemgrProvider interfaceMgrProvider;
53 private final EntityOwnershipUtils entityOwnershipUtils;
54 private final JobCoordinator coordinator;
55 private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
56 private final OvsInterfaceTopologyStateUpdateHelper ovsInterfaceTopologyStateUpdateHelper;
57 private final InterfaceMetaUtils interfaceMetaUtils;
58 private final SouthboundUtils southboundUtils;
61 public InterfaceTopologyStateListener(final DataBroker dataBroker, final InterfacemgrProvider interfaceMgrProvider,
62 final EntityOwnershipUtils entityOwnershipUtils, final JobCoordinator coordinator,
63 final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
64 final OvsInterfaceTopologyStateUpdateHelper ovsInterfaceTopologyStateUpdateHelper,
65 final InterfaceMetaUtils interfaceMetaUtils, final SouthboundUtils southboundUtils,
66 final InterfaceServiceRecoveryHandler interfaceServiceRecoveryHandler) {
67 super(OvsdbBridgeAugmentation.class, InterfaceTopologyStateListener.class);
68 this.dataBroker = dataBroker;
69 this.interfaceMgrProvider = interfaceMgrProvider;
70 this.entityOwnershipUtils = entityOwnershipUtils;
71 this.coordinator = coordinator;
72 this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
73 this.ovsInterfaceTopologyStateUpdateHelper = ovsInterfaceTopologyStateUpdateHelper;
74 this.interfaceMetaUtils = interfaceMetaUtils;
75 this.southboundUtils = southboundUtils;
77 interfaceServiceRecoveryHandler.addRecoverableListener(this);
81 public void registerListener() {
82 this.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
86 public void deregisterListener() {
91 protected InstanceIdentifier<OvsdbBridgeAugmentation> getWildCardPath() {
92 return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).child(Node.class)
93 .augmentation(OvsdbBridgeAugmentation.class).build();
97 protected InterfaceTopologyStateListener getDataTreeChangeListener() {
98 return InterfaceTopologyStateListener.this;
101 private void runOnlyInOwnerNode(String jobDesc, Runnable job) {
102 entityOwnershipUtils.runOnlyInOwnerNode(IfmConstants.INTERFACE_CONFIG_ENTITY,
103 IfmConstants.INTERFACE_CONFIG_ENTITY, coordinator, jobDesc, job);
107 protected void remove(InstanceIdentifier<OvsdbBridgeAugmentation> identifier,
108 OvsdbBridgeAugmentation bridgeOld) {
109 LOG.debug("Received Remove DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
110 identifier, bridgeOld);
112 InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
113 interfaceMgrProvider.removeBridgeForNodeIid(nodeIid);
115 runOnlyInOwnerNode("OVSDB bridge removed", () -> {
116 RendererStateRemoveWorker rendererStateRemoveWorker =
117 new RendererStateRemoveWorker(identifier, bridgeOld);
118 coordinator.enqueueJob(bridgeOld.getBridgeName().getValue(), rendererStateRemoveWorker,
119 IfmConstants.JOB_MAX_RETRIES);
124 protected void update(InstanceIdentifier<OvsdbBridgeAugmentation> identifier,
125 OvsdbBridgeAugmentation bridgeOld,
126 OvsdbBridgeAugmentation bridgeNew) {
128 "Received Update DataChange Notification for identifier: {}, ovsdbBridgeAugmentation old: {}, new: {}.",
129 identifier, bridgeOld, bridgeNew);
131 InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
132 interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
134 runOnlyInOwnerNode("OVSDB bridge updated", () -> {
135 DatapathId oldDpid = bridgeOld.getDatapathId();
136 DatapathId newDpid = bridgeNew.getDatapathId();
137 if (oldDpid == null && newDpid != null) {
138 RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
139 coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
140 IfmConstants.JOB_MAX_RETRIES);
141 } else if (oldDpid != null && !oldDpid.equals(newDpid)) {
142 RendererStateUpdateWorker rendererStateAddWorker =
143 new RendererStateUpdateWorker(identifier, bridgeNew, bridgeOld);
144 coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
145 IfmConstants.JOB_MAX_RETRIES);
151 protected void add(InstanceIdentifier<OvsdbBridgeAugmentation> identifier,
152 OvsdbBridgeAugmentation bridgeNew) {
153 LOG.debug("Received Add DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
154 identifier, bridgeNew);
156 InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
157 interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
159 runOnlyInOwnerNode("OVSDB bridge added", () -> {
160 RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
161 coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
162 IfmConstants.JOB_MAX_RETRIES);
166 private class RendererStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
167 InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
168 OvsdbBridgeAugmentation bridgeNew;
170 RendererStateAddWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
171 OvsdbBridgeAugmentation bridgeNew) {
172 this.instanceIdentifier = instanceIdentifier;
173 this.bridgeNew = bridgeNew;
177 public List<ListenableFuture<Void>> call() {
178 List<ListenableFuture<Void>> futures = new ArrayList<>();
180 if (bridgeNew.getDatapathId() == null) {
181 LOG.info("DataPathId found as null for Bridge Augmentation: {}... returning...", bridgeNew);
184 BigInteger dpnId = IfmUtil.getDpnId(bridgeNew.getDatapathId());
185 LOG.debug("adding bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
186 // create bridge reference entry in interface meta operational DS
187 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
188 InterfaceMetaUtils.createBridgeRefEntry(dpnId, instanceIdentifier, writeTransaction);
190 // handle pre-provisioning of tunnels for the newly connected dpn
191 BridgeEntry bridgeEntry = interfaceMetaUtils.getBridgeEntryFromConfigDS(dpnId);
192 if (bridgeEntry == null) {
193 LOG.debug("Bridge entry not found in config DS for dpn: {}", dpnId);
194 futures.add(writeTransaction.submit());
197 futures.add(writeTransaction.submit());
199 .addAllPortsToBridge(bridgeEntry, interfaceManagerCommonUtils, instanceIdentifier, bridgeNew);
204 private class RendererStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
205 InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
206 OvsdbBridgeAugmentation bridgeNew;
208 RendererStateRemoveWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
209 OvsdbBridgeAugmentation bridgeNew) {
210 this.instanceIdentifier = instanceIdentifier;
211 this.bridgeNew = bridgeNew;
215 public List<ListenableFuture<Void>> call() {
216 BigInteger dpnId = IfmUtil.getDpnId(bridgeNew.getDatapathId());
219 LOG.warn("Got Null DPID for Bridge: {}", bridgeNew);
220 return Collections.emptyList();
223 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
224 LOG.debug("removing bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
225 // delete bridge reference entry in interface meta operational DS
226 InterfaceMetaUtils.deleteBridgeRefEntry(dpnId, transaction);
228 // the bridge reference is copied to dpn-tunnel interfaces map, so that
229 // whenever a northbound delete
230 // happens when bridge is not connected, we need the bridge reference to
231 // clean up the topology config DS
232 InterfaceMetaUtils.addBridgeRefToBridgeInterfaceEntry(dpnId, new OvsdbBridgeRef(instanceIdentifier),
235 return Collections.singletonList(transaction.submit());
239 private class RendererStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
240 InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
241 OvsdbBridgeAugmentation bridgeNew;
242 OvsdbBridgeAugmentation bridgeOld;
244 RendererStateUpdateWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
245 OvsdbBridgeAugmentation bridgeNew, OvsdbBridgeAugmentation bridgeOld) {
246 this.instanceIdentifier = instanceIdentifier;
247 this.bridgeNew = bridgeNew;
248 this.bridgeOld = bridgeOld;
252 public List<ListenableFuture<Void>> call() {
253 return ovsInterfaceTopologyStateUpdateHelper.updateBridgeRefEntry(instanceIdentifier, bridgeNew, bridgeOld);