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 static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.concurrent.Callable;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.apache.aries.blueprint.annotation.service.Reference;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
22 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
23 import org.opendaylight.genius.interfacemanager.IfmConstants;
24 import org.opendaylight.genius.interfacemanager.IfmUtil;
25 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
26 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
27 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
28 import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
29 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
30 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
31 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
32 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
33 import org.opendaylight.infrautils.utils.concurrent.Executors;
34 import org.opendaylight.mdsal.binding.api.DataBroker;
35 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
36 import org.opendaylight.serviceutils.srm.RecoverableListener;
37 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
38 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.common.Uint64;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
52 public class InterfaceTopologyStateListener
53 extends AbstractClusteredAsyncDataTreeChangeListener<OvsdbBridgeAugmentation>
54 implements RecoverableListener {
55 private static final Logger LOG = LoggerFactory.getLogger(InterfaceTopologyStateListener.class);
56 private final DataBroker dataBroker;
57 private final ManagedNewTransactionRunner txRunner;
58 private final InterfacemgrProvider interfaceMgrProvider;
59 private final EntityOwnershipUtils entityOwnershipUtils;
60 private final JobCoordinator coordinator;
61 private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
62 private final OvsInterfaceTopologyStateUpdateHelper ovsInterfaceTopologyStateUpdateHelper;
63 private final InterfaceMetaUtils interfaceMetaUtils;
64 private final SouthboundUtils southboundUtils;
67 public InterfaceTopologyStateListener(@Reference final DataBroker dataBroker,
68 final InterfacemgrProvider interfaceMgrProvider,
69 final EntityOwnershipUtils entityOwnershipUtils,
70 @Reference final JobCoordinator coordinator,
71 final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
72 final OvsInterfaceTopologyStateUpdateHelper
73 ovsInterfaceTopologyStateUpdateHelper,
74 final InterfaceMetaUtils interfaceMetaUtils,
75 final SouthboundUtils southboundUtils,
76 final InterfaceServiceRecoveryHandler interfaceServiceRecoveryHandler,
77 @Reference final ServiceRecoveryRegistry serviceRecoveryRegistry) {
78 super(dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class)
79 .child(Topology.class).child(Node.class).augmentation(OvsdbBridgeAugmentation.class).build(),
80 Executors.newSingleThreadExecutor("InterfaceTopologyStateListener", LOG));
81 this.dataBroker = dataBroker;
82 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
83 this.interfaceMgrProvider = interfaceMgrProvider;
84 this.entityOwnershipUtils = entityOwnershipUtils;
85 this.coordinator = coordinator;
86 this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
87 this.ovsInterfaceTopologyStateUpdateHelper = ovsInterfaceTopologyStateUpdateHelper;
88 this.interfaceMetaUtils = interfaceMetaUtils;
89 this.southboundUtils = southboundUtils;
90 serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(),
95 public void registerListener() {
100 public void deregisterListener() {
104 private void runOnlyInOwnerNode(String jobDesc, Runnable job) {
105 entityOwnershipUtils.runOnlyInOwnerNode(IfmConstants.INTERFACE_CONFIG_ENTITY,
106 IfmConstants.INTERFACE_CONFIG_ENTITY, coordinator, jobDesc, job);
110 public void remove(InstanceIdentifier<OvsdbBridgeAugmentation> identifier,
111 OvsdbBridgeAugmentation bridgeOld) {
112 LOG.debug("Received Remove DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
113 identifier, bridgeOld);
115 InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
116 interfaceMgrProvider.removeBridgeForNodeIid(nodeIid);
118 runOnlyInOwnerNode("OVSDB bridge removed", () -> {
119 RendererStateRemoveWorker rendererStateRemoveWorker =
120 new RendererStateRemoveWorker(identifier, bridgeOld);
121 coordinator.enqueueJob(bridgeOld.getBridgeName().getValue(), rendererStateRemoveWorker,
122 IfmConstants.JOB_MAX_RETRIES);
127 public void update(InstanceIdentifier<OvsdbBridgeAugmentation> identifier,
128 OvsdbBridgeAugmentation bridgeOld,
129 OvsdbBridgeAugmentation bridgeNew) {
131 "Received Update DataChange Notification for identifier: {}, ovsdbBridgeAugmentation old: {}, new: {}.",
132 identifier, bridgeOld, bridgeNew);
134 InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
135 interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
137 runOnlyInOwnerNode("OVSDB bridge updated", () -> {
138 DatapathId oldDpid = bridgeOld.getDatapathId();
139 DatapathId newDpid = bridgeNew.getDatapathId();
140 if (oldDpid == null && newDpid != null) {
141 RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
142 coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
143 IfmConstants.JOB_MAX_RETRIES);
144 } else if (oldDpid != null && !oldDpid.equals(newDpid)) {
145 RendererStateUpdateWorker rendererStateAddWorker =
146 new RendererStateUpdateWorker(identifier, bridgeNew, bridgeOld);
147 coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
148 IfmConstants.JOB_MAX_RETRIES);
154 public void add(InstanceIdentifier<OvsdbBridgeAugmentation> identifier,
155 OvsdbBridgeAugmentation bridgeNew) {
156 LOG.debug("Received Add DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
157 identifier, bridgeNew);
159 InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
160 interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
162 runOnlyInOwnerNode("OVSDB bridge added", () -> {
163 RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
164 coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
165 IfmConstants.JOB_MAX_RETRIES);
169 private class RendererStateAddWorker implements Callable<List<? extends ListenableFuture<?>>> {
170 InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
171 OvsdbBridgeAugmentation bridgeNew;
173 RendererStateAddWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
174 OvsdbBridgeAugmentation bridgeNew) {
175 this.instanceIdentifier = instanceIdentifier;
176 this.bridgeNew = bridgeNew;
180 public List<ListenableFuture<Void>> call() {
181 if (bridgeNew.getDatapathId() == null) {
182 LOG.info("DataPathId found as null for Bridge Augmentation: {}... returning...", bridgeNew);
183 return Collections.emptyList();
185 Uint64 dpnId = IfmUtil.getDpnId(bridgeNew.getDatapathId());
186 LOG.debug("adding bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
187 // create bridge reference entry in interface meta operational DS
188 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
189 InterfaceMetaUtils.createBridgeRefEntry(dpnId, instanceIdentifier, tx);
191 // handle pre-provisioning of tunnels for the newly connected dpn
192 BridgeEntry bridgeEntry = interfaceMetaUtils.getBridgeEntryFromConfigDS(dpnId);
193 if (bridgeEntry == null) {
194 LOG.debug("Bridge entry not found in config DS for dpn: {}", dpnId);
196 southboundUtils.addAllPortsToBridge(bridgeEntry, interfaceManagerCommonUtils, instanceIdentifier,
203 private class RendererStateRemoveWorker implements Callable<List<? extends ListenableFuture<?>>> {
204 InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
205 OvsdbBridgeAugmentation bridgeNew;
207 RendererStateRemoveWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
208 OvsdbBridgeAugmentation bridgeNew) {
209 this.instanceIdentifier = instanceIdentifier;
210 this.bridgeNew = bridgeNew;
214 public List<ListenableFuture<Void>> call() {
215 Uint64 dpnId = IfmUtil.getDpnId(bridgeNew.getDatapathId());
218 LOG.warn("Got Null DPID for Bridge: {}", bridgeNew);
219 return Collections.emptyList();
222 List<ListenableFuture<Void>> futures = new ArrayList<>();
223 LOG.debug("removing bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
224 // TODO skitt Use a transaction chain
225 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
226 // delete bridge reference entry in interface meta operational DS
227 InterfaceMetaUtils.deleteBridgeRefEntry(dpnId, tx);
229 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
230 // the bridge reference is copied to dpn-tunnel interfaces map, so that
231 // whenever a northbound delete
232 // happens when bridge is not connected, we need the bridge reference to
233 // clean up the topology config DS
234 InterfaceMetaUtils.addBridgeRefToBridgeInterfaceEntry(dpnId, new OvsdbBridgeRef(instanceIdentifier),
241 private class RendererStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
242 InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
243 OvsdbBridgeAugmentation bridgeNew;
244 OvsdbBridgeAugmentation bridgeOld;
246 RendererStateUpdateWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
247 OvsdbBridgeAugmentation bridgeNew, OvsdbBridgeAugmentation bridgeOld) {
248 this.instanceIdentifier = instanceIdentifier;
249 this.bridgeNew = bridgeNew;
250 this.bridgeOld = bridgeOld;
254 public List<ListenableFuture<Void>> call() {
255 return ovsInterfaceTopologyStateUpdateHelper.updateBridgeRefEntry(instanceIdentifier, bridgeNew, bridgeOld);