2 * Copyright (c) 2014 Cisco Systems, Inc. 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.groupbasedpolicy.renderer.ofoverlay.node;
11 import com.google.common.base.Objects;
12 import com.google.common.base.Optional;
13 import com.google.common.util.concurrent.Futures;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
16 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
20 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3ContextBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
38 import org.opendaylight.yangtools.concepts.ListenerRegistration;
39 import org.opendaylight.yangtools.yang.binding.DataObject;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 import java.util.Collections;
45 import java.util.HashMap;
47 import java.util.Map.Entry;
49 import static com.google.common.base.Preconditions.checkNotNull;
51 public class FlowCapableNodeConnectorListener implements DataChangeListener, AutoCloseable {
53 private static final Logger LOG = LoggerFactory.getLogger(FlowCapableNodeConnectorListener.class);
55 private final static InstanceIdentifier<FlowCapableNodeConnector> fcNodeConnectorIid = InstanceIdentifier.builder(
58 .child(NodeConnector.class)
59 .augmentation(FlowCapableNodeConnector.class)
61 private final static InstanceIdentifier<Endpoints> endpointsIid = InstanceIdentifier.builder(Endpoints.class)
63 private final DataBroker dataProvider;
64 private final SwitchManager switchManager;
65 private final ListenerRegistration<DataChangeListener> listenerRegistration;
67 public FlowCapableNodeConnectorListener(DataBroker dataProvider, SwitchManager switchManager) {
68 this.dataProvider = checkNotNull(dataProvider);
69 this.switchManager = checkNotNull(switchManager);
70 listenerRegistration = dataProvider.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
71 fcNodeConnectorIid, this, DataChangeScope.BASE);
75 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
76 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
78 //endpoint and endpoint L3 maps
79 Map<Name, Endpoint> epWithOfOverlayAugByPortName = readEpsWithOfOverlayAugByPortName(rwTx);
80 Map<Name, EndpointL3> l3EpWithOfOverlayAugByPortName = readL3EpsWithOfOverlayAugByPortName(rwTx);
82 boolean isDataPutToTx = false;
83 for (Entry<InstanceIdentifier<?>, DataObject> fcncEntry : change.getCreatedData().entrySet()) {
84 if (FlowCapableNodeConnector.class.equals(fcncEntry.getKey().getTargetType())) {
85 InstanceIdentifier<NodeConnector> ncIid = fcncEntry.getKey().firstIdentifierOf(NodeConnector.class);
86 FlowCapableNodeConnector fcnc = (FlowCapableNodeConnector) fcncEntry.getValue();
88 "FlowCapableNodeConnector created: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
89 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
90 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
91 switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
92 Name portName = getPortName(fcnc);
93 boolean updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
94 boolean l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
95 if (updated || l3Updated) {
100 for (Entry<InstanceIdentifier<?>, DataObject> fcncEntry : change.getUpdatedData().entrySet()) {
101 if (FlowCapableNodeConnector.class.equals(fcncEntry.getKey().getTargetType())) {
102 InstanceIdentifier<NodeConnector> ncIid = fcncEntry.getKey().firstIdentifierOf(NodeConnector.class);
103 FlowCapableNodeConnector fcnc = (FlowCapableNodeConnector) fcncEntry.getValue();
105 "FlowCapableNodeConnector updated: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
106 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
107 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
108 switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
109 Name portName = getPortName(fcnc);
110 boolean updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
111 boolean l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
112 if (updated || l3Updated) {
113 isDataPutToTx = true;
115 FlowCapableNodeConnector originalFcnc = (FlowCapableNodeConnector) change.getOriginalData().get(
117 Name portNameFromOriginalFcnc = getPortName(originalFcnc);
118 // port name already existed and then was changed
119 if (portNameFromOriginalFcnc != null && !Objects.equal(portNameFromOriginalFcnc, portName)) {
120 updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName
121 .get(portNameFromOriginalFcnc), null, rwTx);
122 l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName
123 .get(portNameFromOriginalFcnc), null, rwTx);
124 if (updated || l3Updated) {
125 isDataPutToTx = true;
130 for (InstanceIdentifier<?> fcncIid : change.getRemovedPaths()) {
131 if (FlowCapableNodeConnector.class.equals(fcncIid.getTargetType())) {
132 InstanceIdentifier<NodeConnector> ncIid = fcncIid.firstIdentifierOf(NodeConnector.class);
133 FlowCapableNodeConnector originalFcnc = (FlowCapableNodeConnector) change.getOriginalData()
135 LOG.trace("FlowCapableNodeConnector removed: NodeId: {} NodeConnectorId: {}",
136 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
137 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue());
138 switchManager.updateSwitchNodeConnectorConfig(ncIid, null);
139 Name portNameFromOriginalFcnc = getPortName(originalFcnc);
140 boolean updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
141 boolean l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
142 if (updated || l3Updated) {
143 isDataPutToTx = true;
154 //read endpoints from listener entry
155 private Map<Name, Endpoint> readEpsWithOfOverlayAugByPortName(ReadTransaction rTx) {
156 Optional<Endpoints> potentialEps = Futures.getUnchecked(rTx.read(LogicalDatastoreType.OPERATIONAL, endpointsIid));
157 if (!potentialEps.isPresent() || potentialEps.get().getEndpoint() == null) {
158 return Collections.emptyMap();
160 Map<Name, Endpoint> epsByPortName = new HashMap<>();
161 for (Endpoint ep : potentialEps.get().getEndpoint()) {
162 OfOverlayContext ofOverlayEp = ep.getAugmentation(OfOverlayContext.class);
163 if (ofOverlayEp != null && ofOverlayEp.getPortName() != null) {
164 epsByPortName.put(ofOverlayEp.getPortName(), ep);
167 return epsByPortName;
170 //read l3 endpoint from listener entry
171 private Map<Name, EndpointL3> readL3EpsWithOfOverlayAugByPortName(ReadTransaction rTx) {
172 Optional<Endpoints> potentialEps = Futures.getUnchecked(rTx.read(LogicalDatastoreType.OPERATIONAL, endpointsIid));
173 if (!potentialEps.isPresent() || potentialEps.get().getEndpoint() == null) {
174 return Collections.emptyMap();
176 Map<Name, EndpointL3> epsByPortName = new HashMap<>();
177 for (EndpointL3 epL3 : potentialEps.get().getEndpointL3()) {
178 OfOverlayL3Context ofOverlayL3Ep = epL3.getAugmentation(OfOverlayL3Context.class);
179 if (ofOverlayL3Ep != null && ofOverlayL3Ep.getPortName() != null) {
180 epsByPortName.put(ofOverlayL3Ep.getPortName(), epL3);
183 return epsByPortName;
186 private Name getPortName(FlowCapableNodeConnector fcnc) {
187 if (fcnc == null || fcnc.getName() == null) {
190 return new Name(fcnc.getName());
194 * @return {@code true} if data (Endpoint) was put to the transaction; {@code false} otherwise
196 private boolean updateEpWithNodeConnectorInfo(Endpoint epWithOfOverlayAug, InstanceIdentifier<NodeConnector> ncIid,
197 WriteTransaction tx) {
198 if (epWithOfOverlayAug == null) {
201 OfOverlayContext oldOfOverlayAug = epWithOfOverlayAug.getAugmentation(OfOverlayContext.class);
202 OfOverlayContextBuilder newOfOverlayAug = new OfOverlayContextBuilder(oldOfOverlayAug);
203 if (ncIid == null && oldOfOverlayAug.getNodeConnectorId() == null) {
207 NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
208 if (ncId.equals(oldOfOverlayAug.getNodeConnectorId())) {
211 NodeId nodeId = ncIid.firstKeyOf(Node.class, NodeKey.class).getId();
212 newOfOverlayAug.setNodeId(nodeId);
213 newOfOverlayAug.setNodeConnectorId(ncId);
215 //when nodeId is null, remove info about that node from endpoint
216 newOfOverlayAug.setNodeId(null);
217 newOfOverlayAug.setNodeConnectorId(null);
219 InstanceIdentifier<OfOverlayContext> epOfOverlayAugIid = InstanceIdentifier.builder(Endpoints.class)
220 .child(Endpoint.class, epWithOfOverlayAug.getKey())
221 .augmentation(OfOverlayContext.class)
223 tx.put(LogicalDatastoreType.OPERATIONAL, epOfOverlayAugIid, newOfOverlayAug.build());
228 * @return {@code true} if data (EndpointL3) was put to the transaction; {@code false} otherwise
230 private boolean updateL3EpWithNodeConnectorInfo(EndpointL3 epWithOfOverlayL3Aug,
231 InstanceIdentifier<NodeConnector> ncIid, WriteTransaction tx) {
232 if (epWithOfOverlayL3Aug == null) {
235 OfOverlayL3Context oldOfOverlayL3Aug = epWithOfOverlayL3Aug.getAugmentation(OfOverlayL3Context.class);
236 OfOverlayL3ContextBuilder newOfOverlayL3Aug = new OfOverlayL3ContextBuilder(oldOfOverlayL3Aug);
237 if (ncIid == null && oldOfOverlayL3Aug.getNodeConnectorId() == null) {
241 NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
242 if (ncId.equals(oldOfOverlayL3Aug.getNodeConnectorId())) {
245 NodeId nodeId = ncIid.firstKeyOf(Node.class, NodeKey.class).getId();
246 newOfOverlayL3Aug.setNodeId(nodeId);
247 newOfOverlayL3Aug.setNodeConnectorId(ncId);
250 newOfOverlayL3Aug.setNodeId(null);
251 newOfOverlayL3Aug.setNodeConnectorId(null);
253 InstanceIdentifier<OfOverlayL3Context> epOfOverlayAugIid = InstanceIdentifier.builder(Endpoints.class)
254 .child(EndpointL3.class, epWithOfOverlayL3Aug.getKey())
255 .augmentation(OfOverlayL3Context.class)
257 tx.put(LogicalDatastoreType.OPERATIONAL, epOfOverlayAugIid, newOfOverlayL3Aug.build());
262 public void close() throws Exception {
263 if (listenerRegistration != null) {
264 listenerRegistration.close();