1 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node;
3 import static com.google.common.base.Preconditions.checkNotNull;
5 import java.util.Collections;
6 import java.util.HashMap;
8 import java.util.Map.Entry;
10 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
11 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
12 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
13 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
14 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
15 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
16 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
31 import org.opendaylight.yangtools.concepts.ListenerRegistration;
32 import org.opendaylight.yangtools.yang.binding.DataObject;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import com.google.common.base.Objects;
38 import com.google.common.base.Optional;
39 import com.google.common.util.concurrent.Futures;
41 public class FlowCapableNodeConnectorListener implements DataChangeListener, AutoCloseable {
43 private static final Logger LOG = LoggerFactory.getLogger(FlowCapableNodeConnectorListener.class);
45 private final static InstanceIdentifier<FlowCapableNodeConnector> fcNodeConnectorIid = InstanceIdentifier.builder(
48 .child(NodeConnector.class)
49 .augmentation(FlowCapableNodeConnector.class)
51 private final static InstanceIdentifier<Endpoints> endpointsIid = InstanceIdentifier.builder(Endpoints.class)
53 private final DataBroker dataProvider;
54 private final SwitchManager switchManager;
55 private final ListenerRegistration<DataChangeListener> listenerRegistration;
57 public FlowCapableNodeConnectorListener(DataBroker dataProvider, SwitchManager switchManager) {
58 this.dataProvider = checkNotNull(dataProvider);
59 this.switchManager = checkNotNull(switchManager);
60 listenerRegistration = dataProvider.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
61 fcNodeConnectorIid, this, DataChangeScope.BASE);
65 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
66 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
67 Map<Name, Endpoint> epWithOfOverlayAugByPortName = readEpsWithOfOverlayAugByPortName(rwTx);
68 boolean isDataPutToTx = false;
69 for (Entry<InstanceIdentifier<?>, DataObject> fcncEntry : change.getCreatedData().entrySet()) {
70 if (FlowCapableNodeConnector.class.equals(fcncEntry.getKey().getTargetType())) {
71 InstanceIdentifier<NodeConnector> ncIid = fcncEntry.getKey().firstIdentifierOf(NodeConnector.class);
72 FlowCapableNodeConnector fcnc = (FlowCapableNodeConnector) fcncEntry.getValue();
74 "FlowCapableNodeConnector created: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
75 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
76 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
77 switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
78 Name portName = getPortName(fcnc);
79 boolean updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
80 if (updated == true) {
85 for (Entry<InstanceIdentifier<?>, DataObject> fcncEntry : change.getUpdatedData().entrySet()) {
86 if (FlowCapableNodeConnector.class.equals(fcncEntry.getKey().getTargetType())) {
87 InstanceIdentifier<NodeConnector> ncIid = fcncEntry.getKey().firstIdentifierOf(NodeConnector.class);
88 FlowCapableNodeConnector fcnc = (FlowCapableNodeConnector) fcncEntry.getValue();
90 "FlowCapableNodeConnector updated: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
91 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
92 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
93 switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
94 Name portName = getPortName(fcnc);
95 boolean updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
96 if (updated == true) {
99 FlowCapableNodeConnector originalFcnc = (FlowCapableNodeConnector) change.getOriginalData().get(
101 Name portNameFromOriginalFcnc = getPortName(originalFcnc);
102 // portname already existed and then was changed
103 if (portNameFromOriginalFcnc != null && !Objects.equal(portNameFromOriginalFcnc, portName)) {
104 updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc),
106 if (updated == true) {
107 isDataPutToTx = true;
112 for (InstanceIdentifier<?> fcncIid : change.getRemovedPaths()) {
113 if (FlowCapableNodeConnector.class.equals(fcncIid.getTargetType())) {
114 InstanceIdentifier<NodeConnector> ncIid = fcncIid.firstIdentifierOf(NodeConnector.class);
115 FlowCapableNodeConnector originalFcnc = (FlowCapableNodeConnector) change.getOriginalData()
117 LOG.trace("FlowCapableNodeConnector removed: NodeId: {} NodeConnectorId: {}",
118 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
119 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue());
120 switchManager.updateSwitchNodeConnectorConfig(ncIid, null);
121 Name portNameFromOriginalFcnc = getPortName(originalFcnc);
122 boolean updated = updateEpWithNodeConnectorInfo(
123 epWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
124 if (updated == true) {
125 isDataPutToTx = true;
136 private Map<Name, Endpoint> readEpsWithOfOverlayAugByPortName(ReadTransaction rTx) {
137 Optional<Endpoints> potentialEps = Futures.getUnchecked(rTx.read(LogicalDatastoreType.OPERATIONAL, endpointsIid));
138 if (!potentialEps.isPresent() || potentialEps.get().getEndpoint() == null) {
139 return Collections.emptyMap();
141 Map<Name, Endpoint> epsByPortName = new HashMap<>();
142 for (Endpoint ep : potentialEps.get().getEndpoint()) {
143 OfOverlayContext ofOverlayEp = ep.getAugmentation(OfOverlayContext.class);
144 if (ofOverlayEp != null && ofOverlayEp.getPortName() != null) {
145 epsByPortName.put(ofOverlayEp.getPortName(), ep);
148 return epsByPortName;
151 private Name getPortName(FlowCapableNodeConnector fcnc) {
152 if (fcnc == null || fcnc.getName() == null) {
155 return new Name(fcnc.getName());
159 * @return {@code true} if data was put to the transaction; {@code false} otherwise
161 private boolean updateEpWithNodeConnectorInfo(Endpoint epWithOfOverlayAug, InstanceIdentifier<NodeConnector> ncIid,
162 WriteTransaction tx) {
163 if (epWithOfOverlayAug == null) {
166 OfOverlayContext oldOfOverlayAug = epWithOfOverlayAug.getAugmentation(OfOverlayContext.class);
167 OfOverlayContextBuilder newOfOverlayAug = new OfOverlayContextBuilder(oldOfOverlayAug);
168 if (ncIid == null && oldOfOverlayAug.getNodeConnectorId() == null) {
172 NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
173 if (ncId.equals(oldOfOverlayAug.getNodeConnectorId())) {
176 NodeId nodeId = ncIid.firstKeyOf(Node.class, NodeKey.class).getId();
177 newOfOverlayAug.setNodeId(nodeId);
178 newOfOverlayAug.setNodeConnectorId(ncId);
180 InstanceIdentifier<OfOverlayContext> epOfOverlayAugIid = InstanceIdentifier.builder(Endpoints.class)
181 .child(Endpoint.class, epWithOfOverlayAug.getKey())
182 .augmentation(OfOverlayContext.class)
184 tx.put(LogicalDatastoreType.OPERATIONAL, epOfOverlayAugIid, newOfOverlayAug.build());
189 public void close() throws Exception {
190 if (listenerRegistration != null) {
191 listenerRegistration.close();