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 static com.google.common.base.Preconditions.checkNotNull;
13 import com.google.common.base.Objects;
14 import com.google.common.base.Optional;
15 import com.google.common.util.concurrent.Futures;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
25 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
27 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3ContextBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
45 import org.opendaylight.yangtools.concepts.ListenerRegistration;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 public class FlowCapableNodeConnectorListener implements DataTreeChangeListener<FlowCapableNodeConnector>,
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<?> listenerRegistration;
67 public FlowCapableNodeConnectorListener(DataBroker dataProvider, SwitchManager switchManager) {
68 this.dataProvider = checkNotNull(dataProvider);
69 this.switchManager = checkNotNull(switchManager);
70 listenerRegistration = dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
71 LogicalDatastoreType.OPERATIONAL, fcNodeConnectorIid), this);
75 public void onDataTreeChanged(Collection<DataTreeModification<FlowCapableNodeConnector>> changes) {
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 (DataTreeModification<FlowCapableNodeConnector> change: changes) {
84 DataObjectModification<FlowCapableNodeConnector> rootNode = change.getRootNode();
85 InstanceIdentifier<NodeConnector> ncIid = change.getRootPath().getRootIdentifier()
86 .firstIdentifierOf(NodeConnector.class);
87 final FlowCapableNodeConnector originalFcnc = rootNode.getDataBefore();
90 switch (rootNode.getModificationType()) {
91 case SUBTREE_MODIFIED:
93 FlowCapableNodeConnector fcnc = rootNode.getDataAfter();
95 "FlowCapableNodeConnector updated: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
96 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
97 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
98 switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
99 Name portName = getPortName(fcnc);
100 updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
101 l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
102 if (updated || l3Updated) {
103 isDataPutToTx = true;
106 if (originalFcnc != null) {
107 Name portNameFromOriginalFcnc = getPortName(originalFcnc);
108 // port name already existed and then was changed
109 if (portNameFromOriginalFcnc != null && !Objects.equal(portNameFromOriginalFcnc, portName)) {
110 updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName
111 .get(portNameFromOriginalFcnc), null, rwTx);
112 l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName
113 .get(portNameFromOriginalFcnc), null, rwTx);
114 if (updated || l3Updated) {
115 isDataPutToTx = true;
121 LOG.trace("FlowCapableNodeConnector removed: NodeId: {} NodeConnectorId: {}",
122 ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
123 ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue());
124 switchManager.updateSwitchNodeConnectorConfig(ncIid, null);
125 Name portNameFromOriginalFcnc = getPortName(originalFcnc);
126 updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
127 l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
128 if (updated || l3Updated) {
129 isDataPutToTx = true;
144 //read endpoints from listener entry
145 private Map<Name, Endpoint> readEpsWithOfOverlayAugByPortName(ReadTransaction rTx) {
146 Optional<Endpoints> potentialEps = Futures.getUnchecked(rTx.read(LogicalDatastoreType.OPERATIONAL, endpointsIid));
147 if (!potentialEps.isPresent() || potentialEps.get().getEndpoint() == null) {
148 return Collections.emptyMap();
150 Map<Name, Endpoint> epsByPortName = new HashMap<>();
151 for (Endpoint ep : potentialEps.get().getEndpoint()) {
152 OfOverlayContext ofOverlayEp = ep.getAugmentation(OfOverlayContext.class);
153 if (ofOverlayEp != null && ofOverlayEp.getPortName() != null) {
154 epsByPortName.put(ofOverlayEp.getPortName(), ep);
157 return epsByPortName;
160 //read l3 endpoint from listener entry
161 private Map<Name, EndpointL3> readL3EpsWithOfOverlayAugByPortName(ReadTransaction rTx) {
162 Optional<Endpoints> potentialEps = Futures.getUnchecked(rTx.read(LogicalDatastoreType.OPERATIONAL, endpointsIid));
163 if (!potentialEps.isPresent() || potentialEps.get().getEndpoint() == null) {
164 return Collections.emptyMap();
166 Map<Name, EndpointL3> epsByPortName = new HashMap<>();
167 for (EndpointL3 epL3 : potentialEps.get().getEndpointL3()) {
168 OfOverlayL3Context ofOverlayL3Ep = epL3.getAugmentation(OfOverlayL3Context.class);
169 if (ofOverlayL3Ep != null && ofOverlayL3Ep.getPortName() != null) {
170 epsByPortName.put(ofOverlayL3Ep.getPortName(), epL3);
173 return epsByPortName;
176 private Name getPortName(FlowCapableNodeConnector fcnc) {
177 if (fcnc == null || fcnc.getName() == null) {
180 return new Name(fcnc.getName());
184 * @return {@code true} if data (Endpoint) was put to the transaction; {@code false} otherwise
186 private boolean updateEpWithNodeConnectorInfo(Endpoint epWithOfOverlayAug, InstanceIdentifier<NodeConnector> ncIid,
187 WriteTransaction tx) {
188 if (epWithOfOverlayAug == null) {
191 OfOverlayContext oldOfOverlayAug = epWithOfOverlayAug.getAugmentation(OfOverlayContext.class);
192 OfOverlayContextBuilder newOfOverlayAug = new OfOverlayContextBuilder(oldOfOverlayAug);
193 if (ncIid == null && oldOfOverlayAug.getNodeConnectorId() == null) {
197 NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
198 if (ncId.equals(oldOfOverlayAug.getNodeConnectorId())) {
201 NodeId nodeId = ncIid.firstKeyOf(Node.class, NodeKey.class).getId();
202 newOfOverlayAug.setNodeId(nodeId);
203 newOfOverlayAug.setNodeConnectorId(ncId);
205 //when nodeId is null, remove info about that node from endpoint
206 newOfOverlayAug.setNodeId(null);
207 newOfOverlayAug.setNodeConnectorId(null);
209 InstanceIdentifier<OfOverlayContext> epOfOverlayAugIid = InstanceIdentifier.builder(Endpoints.class)
210 .child(Endpoint.class, epWithOfOverlayAug.getKey())
211 .augmentation(OfOverlayContext.class)
213 tx.put(LogicalDatastoreType.OPERATIONAL, epOfOverlayAugIid, newOfOverlayAug.build());
218 * @return {@code true} if data (EndpointL3) was put to the transaction; {@code false} otherwise
220 private boolean updateL3EpWithNodeConnectorInfo(EndpointL3 epWithOfOverlayL3Aug,
221 InstanceIdentifier<NodeConnector> ncIid, WriteTransaction tx) {
222 if (epWithOfOverlayL3Aug == null) {
225 OfOverlayL3Context oldOfOverlayL3Aug = epWithOfOverlayL3Aug.getAugmentation(OfOverlayL3Context.class);
226 OfOverlayL3ContextBuilder newOfOverlayL3Aug = new OfOverlayL3ContextBuilder(oldOfOverlayL3Aug);
227 if (ncIid == null && oldOfOverlayL3Aug.getNodeConnectorId() == null) {
231 NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
232 if (ncId.equals(oldOfOverlayL3Aug.getNodeConnectorId())) {
235 NodeId nodeId = ncIid.firstKeyOf(Node.class, NodeKey.class).getId();
236 newOfOverlayL3Aug.setNodeId(nodeId);
237 newOfOverlayL3Aug.setNodeConnectorId(ncId);
240 newOfOverlayL3Aug.setNodeId(null);
241 newOfOverlayL3Aug.setNodeConnectorId(null);
243 InstanceIdentifier<OfOverlayL3Context> epOfOverlayAugIid = InstanceIdentifier.builder(Endpoints.class)
244 .child(EndpointL3.class, epWithOfOverlayL3Aug.getKey())
245 .augmentation(OfOverlayL3Context.class)
247 tx.put(LogicalDatastoreType.OPERATIONAL, epOfOverlayAugIid, newOfOverlayL3Aug.build());
252 public void close() throws Exception {
253 if (listenerRegistration != null) {
254 listenerRegistration.close();