2 * Copyright (c) 2016 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.itm.listeners;
11 import java.util.List;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
16 import org.opendaylight.genius.itm.impl.ItmUtils;
17 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
18 import org.opendaylight.genius.itm.confighelpers.OvsdbTepAddWorker;
19 import org.opendaylight.genius.itm.confighelpers.OvsdbTepRemoveWorker;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import javax.annotation.PostConstruct;
31 import javax.annotation.PreDestroy;
32 import javax.inject.Inject;
33 import javax.inject.Singleton;
36 * This class listens for OvsdbNode creation/removal/update in Network Topology Operational DS.
37 * This is used to handle add/update/remove of TEPs of switches into/from ITM.
40 public class OvsdbNodeListener extends AsyncDataTreeChangeListenerBase<Node, OvsdbNodeListener>
41 implements AutoCloseable {
42 private static final Logger LOG = LoggerFactory.getLogger(OvsdbNodeListener.class);
43 private DataBroker dataBroker;
46 public OvsdbNodeListener(final DataBroker dataBroker) {
47 super(Node.class, OvsdbNodeListener.class);
48 this.dataBroker = dataBroker;
49 LOG.trace("OvsdbNodeListener Created");
53 public void start() throws Exception {
54 registerListener(this.dataBroker);
55 LOG.info("OvsdbNodeListener Started");
60 public void close() throws Exception {
61 LOG.trace("OvsdbNodeListener Closed");
64 private void registerListener(final DataBroker db) {
66 registerListener(LogicalDatastoreType.OPERATIONAL, db);
67 } catch (final Exception e) {
68 LOG.error("Network Topology Node listener registration failed.", e);
69 throw new IllegalStateException("Network Topology Node listener registration failed.", e);
73 @Override protected InstanceIdentifier<Node> getWildCardPath() {
74 return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class)
75 .child(Node.class).build();
78 @Override protected OvsdbNodeListener getDataTreeChangeListener() {
79 return OvsdbNodeListener.this;
82 @Override protected void remove(InstanceIdentifier<Node> identifier, Node ovsdbNode) {
83 LOG.trace("OvsdbNodeListener called for Ovsdb Node Remove.");
86 @Override protected void add(InstanceIdentifier<Node> identifier, Node ovsdbNodeNew) {
87 String newTepIp = "", tzName = "", dpnBridgeName = "", bridgeName = "";
89 OvsdbNodeAugmentation ovsdbNewNodeAugmentation = null;
91 LOG.trace("OvsdbNodeListener called for Ovsdb Node ({}) Add.",
92 ovsdbNodeNew.getNodeId().getValue());
94 // check for OVS bridge node
95 OvsdbBridgeAugmentation ovsdbNewBridgeAugmentation =
96 ovsdbNodeNew.getAugmentation(OvsdbBridgeAugmentation.class);
97 if (ovsdbNewBridgeAugmentation != null) {
98 bridgeName = ovsdbNewBridgeAugmentation.getBridgeName().getValue();
100 // Read DPN ID from OVSDBBridgeAugmentation
101 strDpnId = ItmUtils.getStrDatapathId(ovsdbNodeNew);
102 if (strDpnId == null || strDpnId.isEmpty()) {
103 LOG.error("OvsdbBridgeAugmentation ADD: DPID for bridge {} is NULL.",
108 Node ovsdbNodeFromBridge = ItmUtils.getOvsdbNode(ovsdbNewBridgeAugmentation, dataBroker);
109 // check for OVSDB node
110 if (ovsdbNodeFromBridge != null) {
111 ovsdbNewNodeAugmentation = ovsdbNodeFromBridge.getAugmentation(OvsdbNodeAugmentation.class);
113 LOG.error("Ovsdb Node could not be fetched from Oper DS for bridge {}.",
119 if (ovsdbNewNodeAugmentation != null) {
120 // get OVSDB other_configs list from old ovsdb node
121 OvsdbOtherConfigInfo ovsdbOtherConfigObj = getOvsdbNodeOtherConfigs(ovsdbNewNodeAugmentation);
122 if (ovsdbOtherConfigObj == null) {
125 // store other config required parameters
126 newTepIp = ovsdbOtherConfigObj.getTepIp();
127 tzName = ovsdbOtherConfigObj.getTzName();
128 dpnBridgeName = ovsdbOtherConfigObj.getDpnBrName();
130 // if bridge received is the one configured for TEPs from OVS side or
131 // if it is br-int, then add TEP into Config DS
132 if (dpnBridgeName.equals(bridgeName)) {
133 // check if TEP-IP is configured or not
134 if (!newTepIp.isEmpty()) {
135 LOG.trace("Ovs Node [{}] is configured with TEP-IP.",
136 ovsdbNodeNew.getNodeId().getValue());
138 LOG.trace("Ovs Node [{}] is not configured with TEP-IP. Nothing to do.",
139 ovsdbNodeNew.getNodeId().getValue());
143 LOG.trace("TEP-IP: {}, TZ name: {}, DPN Bridge Name: {}, Bridge DPID: {}", newTepIp,
144 tzName, dpnBridgeName, strDpnId);
146 // Enqueue 'add TEP received from southbound OVSDB into ITM config DS' operation
147 // into DataStoreJobCoordinator
148 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
149 OvsdbTepAddWorker addWorker =
150 new OvsdbTepAddWorker(newTepIp, strDpnId, tzName, dataBroker);
151 coordinator.enqueueJob(newTepIp, addWorker);
156 @Override protected void update(InstanceIdentifier<Node> identifier, Node ovsdbNodeOld,
158 String newTepIp = "", oldTepIp = "";
159 String tzName = "", oldTzName = "";
160 String oldDpnBridgeName = "", newDpnBridgeName = "";
161 boolean isOtherConfigUpdated = false, isOtherConfigDeleted = false;
162 boolean isTepIpAdded = false, isTepIpRemoved = false;
163 boolean isTzChanged = false, isDpnBrChanged = false;
165 LOG.trace("OvsdbNodeListener called for Ovsdb Node ({}) Update.",
166 ovsdbNodeOld.getNodeId().getValue());
168 // get OVSDB other_configs list from old ovsdb node
169 OvsdbOtherConfigInfo newOtherConfigsInfoObj = getOvsdbNodeOtherConfigs(
170 ovsdbNodeNew.getAugmentation(OvsdbNodeAugmentation.class));
172 // get OVSDB other_configs list from new ovsdb node
173 OvsdbOtherConfigInfo oldOtherConfigInfoObj = getOvsdbNodeOtherConfigs(
174 ovsdbNodeOld.getAugmentation(OvsdbNodeAugmentation.class));
176 if (oldOtherConfigInfoObj == null && newOtherConfigsInfoObj == null) {
177 LOG.trace("OtherConfig is not received in old and new Ovsdb Nodes.");
181 if (oldOtherConfigInfoObj != null && newOtherConfigsInfoObj == null) {
182 isOtherConfigDeleted = true;
183 LOG.trace("OtherConfig is deleted from Ovsdb node: {}",
184 ovsdbNodeOld.getNodeId().getValue());
187 // store other config required parameters
188 if (newOtherConfigsInfoObj != null) {
189 newTepIp = newOtherConfigsInfoObj.getTepIp();
190 tzName = newOtherConfigsInfoObj.getTzName();
191 newDpnBridgeName = newOtherConfigsInfoObj.getDpnBrName();
193 // All map params have been read, now clear it up.
194 newOtherConfigsInfoObj = null;
197 if (oldOtherConfigInfoObj != null) {
198 oldDpnBridgeName = oldOtherConfigInfoObj.getDpnBrName();
199 oldTzName = oldOtherConfigInfoObj.getTzName();
200 oldTepIp = oldOtherConfigInfoObj.getTepIp();
202 // All map params have been read, now clear it up.
203 oldOtherConfigInfoObj = null;
206 if (!isOtherConfigDeleted) {
207 isTepIpRemoved = isTepIpRemoved(oldTepIp, newTepIp);
208 isTepIpAdded = isTepIpAdded(oldTepIp, newTepIp);
210 if (!oldTepIp.equals(newTepIp)) {
211 isOtherConfigUpdated = true;
213 if (!oldTzName.equals(tzName)) {
214 isOtherConfigUpdated = true;
215 if (!oldTepIp.isEmpty() && !newTepIp.isEmpty()) {
217 LOG.trace("tzname is changed from {} to {} for TEP-IP: {}", oldTzName, tzName, newTepIp);
220 if (!oldDpnBridgeName.equals(newDpnBridgeName)) {
221 isOtherConfigUpdated = true;
222 if (!oldTepIp.isEmpty() && !newTepIp.isEmpty()) {
223 isDpnBrChanged = true;
224 LOG.trace("dpn-br-name is changed from {} to {} for TEP-IP: {}", oldDpnBridgeName, newDpnBridgeName, newTepIp);
228 if (!isOtherConfigUpdated) {
229 LOG.trace("No updates in the other config parameters. Nothing to do.");
234 String strOldDpnId = "", strNewDpnId = "";
235 // handle TEP-remove in remove case, TZ change case, Bridge change case
236 if (isOtherConfigDeleted || isTepIpRemoved || isTzChanged || isDpnBrChanged) {
237 strOldDpnId = ItmUtils.getBridgeDpid(ovsdbNodeNew, oldDpnBridgeName,
239 if (strOldDpnId == null || strOldDpnId.isEmpty()) {
241 "TEP {} cannot be deleted. DPN-ID for bridge {} is NULL.",
242 oldTepIp, oldDpnBridgeName);
247 "Update case: Removing TEP-IP: {}, TZ name: {}, DPN Bridge Name: {}, Bridge DPID: {}",
248 oldTepIp, oldTzName, oldDpnBridgeName, strOldDpnId);
250 // Enqueue 'remove TEP from TZ' operation into DataStoreJobCoordinator
251 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
253 removeWorker = new OvsdbTepRemoveWorker(oldTepIp, strOldDpnId, oldTzName, dataBroker);
254 coordinator.enqueueJob(oldTepIp, removeWorker);
256 // handle TEP-add in add case, TZ change case, Bridge change case
257 if (isTepIpAdded || isTzChanged || isDpnBrChanged) {
258 // get Datapath ID for bridge
259 strNewDpnId = ItmUtils.getBridgeDpid(ovsdbNodeNew, newDpnBridgeName,
261 if (strNewDpnId == null || strNewDpnId.isEmpty()) {
263 "TEP {} cannot be added. DPN-ID for bridge {} is NULL.",
264 newTepIp, newDpnBridgeName);
268 "Update case: Adding TEP-IP: {}, TZ name: {}, DPN Bridge Name: {}, Bridge DPID: {}",
269 newTepIp, tzName, newDpnBridgeName, strNewDpnId);
271 // Enqueue 'add TEP into new TZ' operation into DataStoreJobCoordinator
272 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
274 addWorker = new OvsdbTepAddWorker(newTepIp, strNewDpnId, tzName, dataBroker);
275 coordinator.enqueueJob(newTepIp, addWorker);
279 public boolean isTepIpRemoved(String oldTepIp, String newTepIp) {
280 if (!oldTepIp.isEmpty() && newTepIp.isEmpty()) {
286 public boolean isTepIpAdded(String oldTepIp, String newTepIp) {
287 if (oldTepIp.isEmpty() && !newTepIp.isEmpty()) {
293 public OvsdbOtherConfigInfo getOvsdbNodeOtherConfigs(OvsdbNodeAugmentation ovsdbNodeAugmentation) {
294 String tepIp = "", tzName = "", dpnBridgeName = "";
296 if (ovsdbNodeAugmentation == null) {
300 List<OpenvswitchOtherConfigs> ovsdbNodeOtherConfigsList =
301 ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
302 if (ovsdbNodeOtherConfigsList == null) {
303 LOG.error("Other-configs list does not exist in the OVSDB Node Augmentation.");
307 OvsdbOtherConfigInfo otherConfigInfoObj = new OvsdbOtherConfigInfo();
309 if (otherConfigInfoObj == null) {
310 LOG.error("Memory could not be allocated. System fatal error.");
314 if (ovsdbNodeOtherConfigsList != null) {
315 for (OpenvswitchOtherConfigs otherConfig : ovsdbNodeOtherConfigsList) {
316 if (otherConfig.getOtherConfigKey().equals("tep-ip")) {
317 tepIp = otherConfig.getOtherConfigValue();
318 otherConfigInfoObj.setTepIp(tepIp);
319 } else if (otherConfig.getOtherConfigKey().equals("tzname")) {
320 tzName = otherConfig.getOtherConfigValue();
321 otherConfigInfoObj.setTzName(tzName);
322 } else if (otherConfig.getOtherConfigKey().equals("dpn-br-name")) {
323 dpnBridgeName = otherConfig.getOtherConfigValue();
324 otherConfigInfoObj.setDpnBrName(dpnBridgeName);
326 LOG.trace("other_config {}:{}", otherConfig.getOtherConfigKey(),
327 otherConfig.getOtherConfigValue());
330 LOG.trace("{}", otherConfigInfoObj.toString());
332 return otherConfigInfoObj;