package org.opendaylight.openflowplugin.applications.lldpspeaker;
+import com.google.common.collect.Iterables;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
+import java.util.HashMap;
import com.google.common.collect.ImmutableSet;
import java.util.Map;
import java.util.Set;
* and update LLDPSpeaker and topology.
*/
public class NodeConnectorInventoryEventTranslator implements DataChangeListener, AutoCloseable {
+ /**
+ *
+ */
+ private static final InstanceIdentifier<State> II_TO_STATE
+ = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class)
+ .child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnector.class)
+ .child(State.class)
+ .build();
+
+ private static final InstanceIdentifier<FlowCapableNodeConnector> II_TO_FLOW_CAPABLE_NODE_CONNECTOR
+ = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class)
+ .child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnector.class)
+ .build();
+
private static final Logger LOG = LoggerFactory.getLogger(NodeConnectorInventoryEventTranslator.class);
private final ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ private final ListenerRegistration<DataChangeListener> listenerOnPortStateRegistration;
private final Set<NodeConnectorEventsObserver> observers;
+ private final Map<InstanceIdentifier<?>,FlowCapableNodeConnector> iiToDownFlowCapableNodeConnectors = new HashMap<>();
public NodeConnectorInventoryEventTranslator(DataBroker dataBroker, NodeConnectorEventsObserver... observers) {
this.observers = ImmutableSet.copyOf(observers);
dataChangeListenerRegistration = dataBroker.registerDataChangeListener(
LogicalDatastoreType.OPERATIONAL,
- InstanceIdentifier.builder(Nodes.class)
- .child(Node.class)
- .child(NodeConnector.class)
- .augmentation(FlowCapableNodeConnector.class)
- .build(),
+ II_TO_FLOW_CAPABLE_NODE_CONNECTOR,
this, AsyncDataBroker.DataChangeScope.BASE);
+ listenerOnPortStateRegistration = dataBroker.registerDataChangeListener(
+ LogicalDatastoreType.OPERATIONAL,
+ II_TO_STATE,
+ this, AsyncDataBroker.DataChangeScope.SUBTREE);
}
@Override
public void close() {
dataChangeListenerRegistration.close();
+ listenerOnPortStateRegistration.close();
}
@Override
for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : change.getCreatedData().entrySet()) {
InstanceIdentifier<NodeConnector> nodeConnectorInstanceId =
entry.getKey().firstIdentifierOf(NodeConnector.class);
-
- FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue();
- if (!isPortDown(flowConnector)) {
- notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector);
+ if (compareIITail(entry.getKey(),II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
+ FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue();
+ if (!isPortDown(flowConnector)) {
+ notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector);
+ } else {
+ iiToDownFlowCapableNodeConnectors.put(nodeConnectorInstanceId, flowConnector);
+ }
}
}
for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : change.getUpdatedData().entrySet()) {
InstanceIdentifier<NodeConnector> nodeConnectorInstanceId =
entry.getKey().firstIdentifierOf(NodeConnector.class);
- FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue();
- if (isPortDown(flowConnector)) {
- notifyNodeConnectorDisappeared(nodeConnectorInstanceId);
- } else {
- notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector);
+ if (compareIITail(entry.getKey(),II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
+ FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue();
+ if (isPortDown(flowConnector)) {
+ notifyNodeConnectorDisappeared(nodeConnectorInstanceId);
+ } else {
+ notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector);
+ }
+ } else if (compareIITail(entry.getKey(),II_TO_STATE)) {
+ FlowCapableNodeConnector flowNodeConnector = iiToDownFlowCapableNodeConnectors.get(nodeConnectorInstanceId);
+ if (flowNodeConnector != null) {
+ State state = (State)entry.getValue();
+ if (!state.isLinkDown()) {
+ FlowCapableNodeConnectorBuilder flowCapableNodeConnectorBuilder = new FlowCapableNodeConnectorBuilder(flowNodeConnector);
+ flowCapableNodeConnectorBuilder.setState(state);
+ notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowCapableNodeConnectorBuilder.build());
+ iiToDownFlowCapableNodeConnectors.remove(nodeConnectorInstanceId);
+ }
+ }
}
}
// Iterate over removed node connectors
for (InstanceIdentifier<?> removed : change.getRemovedPaths()) {
- InstanceIdentifier<NodeConnector> nodeConnectorInstanceId = removed.firstIdentifierOf(NodeConnector.class);
- notifyNodeConnectorDisappeared(nodeConnectorInstanceId);
+ if (compareIITail(removed,II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
+ InstanceIdentifier<NodeConnector> nodeConnectorInstanceId = removed.firstIdentifierOf(NodeConnector.class);
+ notifyNodeConnectorDisappeared(nodeConnectorInstanceId);
+ }
}
}
+ /**
+ * @param key
+ * @param iiToFlowCapableNodeConnector
+ * @return
+ */
+ private boolean compareIITail(InstanceIdentifier<?> ii1,
+ InstanceIdentifier<?> ii2) {
+ return Iterables.getLast(ii1.getPathArguments()).equals(Iterables.getLast(ii2.getPathArguments()));
+ }
+
private static boolean isPortDown(FlowCapableNodeConnector flowCapableNodeConnector) {
PortState portState = flowCapableNodeConnector.getState();
PortConfig portConfig = flowCapableNodeConnector.getConfiguration();
@RunWith(MockitoJUnitRunner.class)
public class NodeConnectorInventoryEventTranslatorTest {
static InstanceIdentifier<NodeConnector> id = TestUtils.createNodeConnectorId("openflow:1", "openflow:1:1");
+ static InstanceIdentifier<FlowCapableNodeConnector> iiToConnector = id.augmentation(FlowCapableNodeConnector.class);
static FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector().build();
@Mock DataBroker dataBroker;
@Before
public void setUp() {
+
when(dataBroker.registerDataChangeListener(
any(LogicalDatastoreType.class),
any(InstanceIdentifier.class),
@Test
public void testNodeConnectorCreation() {
// Setup dataChangedEvent to mock new port creation in inventory
- dataChangedEvent.created.put(id, fcnc);
+ dataChangedEvent.created.put(iiToConnector, fcnc);
// Invoke NodeConnectorInventoryEventTranslator and check result
translator.onDataChanged(dataChangedEvent);
FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(true, false).build();
// Setup dataChangedEvent to mock link down
- dataChangedEvent.updated.put(id, fcnc);
+ dataChangedEvent.updated.put(iiToConnector, fcnc);
// Invoke NodeConnectorInventoryEventTranslator and check result
translator.onDataChanged(dataChangedEvent);
FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(false, true).build();
// Setup dataChangedEvent to mock link down and administrative port down
- dataChangedEvent.updated.put(id, fcnc);
+ dataChangedEvent.updated.put(iiToConnector, fcnc);
// Invoke NodeConnectorInventoryEventTranslator and check result
translator.onDataChanged(dataChangedEvent);
@Test
public void testNodeConnectorUpdateToUp() {
// Setup dataChangedEvent to mock link up and administrative port up
- dataChangedEvent.updated.put(id, fcnc);
+ dataChangedEvent.updated.put(iiToConnector, fcnc);
// Invoke NodeConnectorInventoryEventTranslator and check result
translator.onDataChanged(dataChangedEvent);
@Test
public void testNodeConnectorRemoval() {
// Setup dataChangedEvent to mock node connector removal
- dataChangedEvent.removed.add(id);
+ dataChangedEvent.removed.add(iiToConnector);
// Invoke NodeConnectorInventoryEventTranslator and check result
translator.onDataChanged(dataChangedEvent);
public void testMultipleObserversNotified() throws Exception {
// Create prerequisites
InstanceIdentifier<NodeConnector> id2 = TestUtils.createNodeConnectorId("openflow:1", "openflow:1:2");
+ InstanceIdentifier<FlowCapableNodeConnector> iiToConnector2 = id2.augmentation(FlowCapableNodeConnector.class);
// Setup dataChangedEvent to mock port creation and removal
- dataChangedEvent.created.put(id, fcnc);
- dataChangedEvent.removed.add(id2);
+ dataChangedEvent.created.put(iiToConnector, fcnc);
+ dataChangedEvent.removed.add(iiToConnector2);
// Invoke onDataChanged and check that both observers notified
translator.onDataChanged(dataChangedEvent);
translator.close();
// Verify that ListenerRegistration to DOM events
- verify(dataChangeListenerRegistration).close();
+ verify(dataChangeListenerRegistration, times(2)).close();
}
static class MockDataChangedEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {