<artifactId>southbound-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>utils.mdsal-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>library</artifactId>
*/
package org.opendaylight.ovsdb.southbound;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import org.opendaylight.ovsdb.lib.MonitorCallBack;
import org.opendaylight.ovsdb.lib.message.TableUpdates;
import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
private final InstanceIdentifierCodec instanceIdentifierCodec;
private TransactionInvoker txInvoker;
private OvsdbConnectionInstance key;
+ private AtomicBoolean intialUpdate = new AtomicBoolean(false);
OvsdbMonitorCallback(InstanceIdentifierCodec instanceIdentifierCodec, OvsdbConnectionInstance key,
TransactionInvoker txInvoker) {
@Override
public void update(TableUpdates result, DatabaseSchema dbSchema) {
- txInvoker.invoke(new OvsdbOperationalCommandAggregator(instanceIdentifierCodec, key, result, dbSchema));
+ boolean isFirstUpdate = intialUpdate.compareAndSet(false, true);
+ txInvoker.invoke(new OvsdbOperationalCommandAggregator(instanceIdentifierCodec, key, result,
+ dbSchema, isFirstUpdate));
LOG.trace("Updated dbSchema: {} and result: {}", dbSchema, result);
}
private final Map<UUID,Bridge> updatedBridgeRows;
private final Map<UUID, Bridge> oldBridgeRows;
private final List<InstanceIdentifier<Node>> updatedBridges = new ArrayList<>();
+ private final Map<NodeId, Node> updatedBridgeNodes;
public OvsdbBridgeUpdateCommand(InstanceIdentifierCodec instanceIdentifierCodec, OvsdbConnectionInstance key,
- TableUpdates updates, DatabaseSchema dbSchema) {
+ TableUpdates updates, DatabaseSchema dbSchema,
+ Map<NodeId, Node> updatedBridgeNodes) {
super(key,updates,dbSchema);
this.instanceIdentifierCodec = instanceIdentifierCodec;
updatedBridgeRows = TyperUtils.extractRowsUpdated(Bridge.class, getUpdates(), getDbSchema());
oldBridgeRows = TyperUtils.extractRowsOld(Bridge.class, getUpdates(), getDbSchema());
+ this.updatedBridgeNodes = updatedBridgeNodes;
}
@Override
Node bridgeNode = buildBridgeNode(bridge);
transaction.merge(LogicalDatastoreType.OPERATIONAL, bridgeIid, bridgeNode);
updatedBridges.add(bridgeIid);
+ updatedBridgeNodes.put(getNodeId(bridge), bridgeNode);
deleteEntries(transaction, protocolEntriesToRemove(bridgeIid, bridge));
deleteEntries(transaction, externalIdsToRemove(bridgeIid,bridge));
deleteEntries(transaction, bridgeOtherConfigsToRemove(bridgeIid,bridge));
--- /dev/null
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.transactions.md;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.message.TableUpdates;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class OvsdbInitialPortUpdateCommand extends OvsdbPortUpdateCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsdbInitialPortUpdateCommand.class);
+ private final Map<NodeId, Node> updatedBridgeNodes;
+ private final Map<NodeId, List<TerminationPoint>> brigeToTerminationPointList = new HashMap<>();
+
+ public OvsdbInitialPortUpdateCommand(InstanceIdentifierCodec instanceIdentifierCodec, OvsdbConnectionInstance key,
+ TableUpdates updates, DatabaseSchema dbSchema,
+ Map<NodeId, Node> updatedBridgeNodes) {
+ super(instanceIdentifierCodec, key, updates, dbSchema);
+ this.updatedBridgeNodes = updatedBridgeNodes;
+ }
+
+ @Override
+ public void execute(ReadWriteTransaction transaction) {
+ super.execute(transaction);
+ mergeToBridgeNode(transaction);
+ }
+
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ protected void updateToDataStore(ReadWriteTransaction transaction, TerminationPointBuilder tpBuilder,
+ InstanceIdentifier<TerminationPoint> tpPath, boolean merge) {
+ try {
+ NodeId bridgeNodeId = tpPath.firstKeyOf(Node.class).getNodeId();
+ TerminationPoint terminationPoint = tpBuilder.build();
+ if (updatedBridgeNodes.containsKey(bridgeNodeId)) {
+ if (brigeToTerminationPointList.containsKey(bridgeNodeId)) {
+ brigeToTerminationPointList.get(bridgeNodeId).add(terminationPoint);
+ } else {
+ List<TerminationPoint> terminationPointList = new ArrayList<>();
+ terminationPointList.add(terminationPoint);
+ brigeToTerminationPointList.put(bridgeNodeId, terminationPointList);
+ }
+ LOG.debug("DEVICE - {} Initial TerminationPoint : {} to Bridge : {}", TransactionType.ADD,
+ terminationPoint.key().getTpId().getValue(), bridgeNodeId.getValue());
+ }
+ }
+ catch (RuntimeException exp) {
+ LOG.error("Exception in adding the terminationPoint {} to bridge ", tpPath);
+ }
+
+ }
+
+ private void mergeToBridgeNode(ReadWriteTransaction transaction) {
+
+ brigeToTerminationPointList.forEach((nodeId, terminationPoints) -> {
+ InstanceIdentifier<Node> bridgeIid = SouthboundMapper.createInstanceIdentifier(nodeId);
+ StringBuilder terminationPointList = new StringBuilder();
+ Node bridgeNode = updatedBridgeNodes.get(nodeId);
+ if (bridgeNode != null) {
+ NodeBuilder bridgeNodeBuilder = new NodeBuilder(bridgeNode);
+ bridgeNodeBuilder.setTerminationPoint(terminationPoints);
+ Node bridgeNodeWithTerminationPoints = bridgeNodeBuilder.build();
+ transaction.merge(LogicalDatastoreType.OPERATIONAL, bridgeIid, bridgeNodeWithTerminationPoints);
+ }
+ terminationPoints.forEach(terminationPoint -> {
+ terminationPointList.append(terminationPoint.key().getTpId().getValue() + ",");
+ });
+ LOG.info("DEVICE - {} Initial TerminationPoint List : {} to Bridge : {}", TransactionType.ADD,
+ terminationPointList.toString(), bridgeIid.firstKeyOf(Node.class).getNodeId().getValue());
+ });
+ }
+}
package org.opendaylight.ovsdb.southbound.transactions.md;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.NoSuchElementException;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.ovsdb.lib.message.TableUpdates;
import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(OvsdbOperationalCommandAggregator.class);
private final List<TransactionCommand> commands = new ArrayList<>();
+ private final Map<NodeId, Node> updatedBridgeNodes = new HashMap<>();
+ private boolean initialUpdate;
public OvsdbOperationalCommandAggregator(InstanceIdentifierCodec instanceIdentifierCodec,
- OvsdbConnectionInstance key, TableUpdates updates, DatabaseSchema dbSchema) {
+ OvsdbConnectionInstance key, TableUpdates updates, DatabaseSchema dbSchema, boolean initialUpdate) {
+ this.initialUpdate = initialUpdate;
commands.add(new OpenVSwitchUpdateCommand(instanceIdentifierCodec, key, updates, dbSchema));
commands.add(new OvsdbManagersUpdateCommand(key, updates, dbSchema));
commands.add(new OvsdbManagersRemovedCommand(key, updates, dbSchema));
commands.add(new OvsdbQosRemovedCommand(key, updates, dbSchema));
commands.add(new OvsdbQueueUpdateCommand(instanceIdentifierCodec, key, updates, dbSchema));
commands.add(new OvsdbQueueRemovedCommand(key, updates, dbSchema));
- commands.add(new OvsdbBridgeUpdateCommand(instanceIdentifierCodec, key, updates, dbSchema));
+ commands.add(new OvsdbBridgeUpdateCommand(instanceIdentifierCodec, key, updates, dbSchema,
+ updatedBridgeNodes));
commands.add(new OvsdbBridgeRemovedCommand(instanceIdentifierCodec, key, updates, dbSchema));
commands.add(new OvsdbControllerUpdateCommand(key, updates, dbSchema));
commands.add(new OvsdbControllerRemovedCommand(instanceIdentifierCodec, key, updates, dbSchema));
- commands.add(new OvsdbPortUpdateCommand(instanceIdentifierCodec, key, updates, dbSchema));
+ if (initialUpdate) {
+ commands.add(new OvsdbInitialPortUpdateCommand(instanceIdentifierCodec, key, updates, dbSchema,
+ updatedBridgeNodes));
+ } else {
+ commands.add(new OvsdbPortUpdateCommand(instanceIdentifierCodec, key, updates, dbSchema));
+ }
commands.add(new OvsdbPortRemoveCommand(instanceIdentifierCodec, key, updates, dbSchema));
if (dbSchema.getVersion().compareTo(
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
import org.opendaylight.ovsdb.southbound.SouthboundMapper;
import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
bridgeIid = getTerminationPointBridge(transaction, node, portName);
}
if (bridgeIid.isPresent()) {
+ NodeId bridgeId = SouthboundMapper.createManagedNodeId(bridgeIid.get());
TerminationPointKey tpKey = new TerminationPointKey(new TpId(portName));
TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
tpBuilder.withKey(tpKey);
}
tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
if (portOldRows.containsKey(portUpdate.getKey()) && !portQosCleared(portUpdate)) {
- transaction.merge(LogicalDatastoreType.OPERATIONAL,
- tpPath, tpBuilder.build());
+ updateToDataStore(transaction, tpBuilder, tpPath, true);
+ LOG.info("DEVICE - {} TerminationPoint : {} to Bridge : {}", TransactionType.ADD,
+ tpKey.getTpId().getValue(), bridgeId.getValue());
} else {
- transaction.put(LogicalDatastoreType.OPERATIONAL,
- tpPath, tpBuilder.build());
+ updateToDataStore(transaction, tpBuilder, tpPath, false);
+ LOG.debug("DEVICE - {} TerminationPoint : {} to Bridge : {}", TransactionType.UPDATE,
+ tpKey.getTpId().getValue(), bridgeId.getValue());
}
}
}
.child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
.child(Node.class,new NodeKey(bridgeId))
.child(TerminationPoint.class,tpKey);
- transaction.merge(LogicalDatastoreType.OPERATIONAL,
- tpPath, tpBuilder.build());
+ updateToDataStore(transaction, tpBuilder, tpPath, true);
}
}
}
+ protected void updateToDataStore(ReadWriteTransaction transaction, TerminationPointBuilder tpBuilder,
+ InstanceIdentifier<TerminationPoint> tpPath, boolean merge) {
+ if (merge) {
+ transaction.merge(LogicalDatastoreType.OPERATIONAL,
+ tpPath, tpBuilder.build());
+ } else {
+ transaction.put(LogicalDatastoreType.OPERATIONAL,
+ tpPath, tpBuilder.build());
+ }
+ }
+
@VisibleForTesting
void buildTerminationPoint(ReadWriteTransaction transaction,
InstanceIdentifier<TerminationPoint> tpPath,
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.opendaylight.ovsdb.southbound.transactions.md.OvsdbOperationalCommandAggregator;
import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvoker;
+
@RunWith(MockitoJUnitRunner.class)
public class OvsdbMonitorCallbackTest {
private TransactionInvoker txInvoker;
@Mock
private OvsdbConnectionInstance key;
+ @Mock
+ private AtomicBoolean intialUpdate;
@Test
public void testUpdate() {
private final Map<UUID,Bridge> updatedBridgeRows = new HashMap<>();
private final Map<UUID, Bridge> oldBridgeRows = new HashMap<>();
private OvsdbBridgeUpdateCommand ovsdbBridgeUpdateCommand;
+ private Map<NodeId, Node> updatedBridgeNodes = new HashMap<>();
@Before
public void setUp() throws Exception {
.set(ovsdbBridgeUpdateCommand, new ArrayList<>());
MemberModifier.field(OvsdbBridgeUpdateCommand.class, "updatedBridgeRows").set(ovsdbBridgeUpdateCommand,
updatedBridgeRows);
+ MemberModifier.field(OvsdbBridgeUpdateCommand.class, "updatedBridgeNodes").set(
+ ovsdbBridgeUpdateCommand,updatedBridgeNodes);
}
@Test
TableUpdates updates = mock(TableUpdates.class);
DatabaseSchema dbSchema = mock(DatabaseSchema.class);
OvsdbBridgeUpdateCommand ovsdbBridgeUpdateCommand1 =
- new OvsdbBridgeUpdateCommand(mock(InstanceIdentifierCodec.class), key, updates, dbSchema);
+ new OvsdbBridgeUpdateCommand(mock(InstanceIdentifierCodec.class), key, updates, dbSchema,
+ updatedBridgeNodes);
assertEquals(key, Whitebox.getInternalState(ovsdbBridgeUpdateCommand1, "key"));
assertEquals(updates, Whitebox.getInternalState(ovsdbBridgeUpdateCommand1, "updates"));
assertEquals(dbSchema, Whitebox.getInternalState(ovsdbBridgeUpdateCommand1, "dbSchema"));
InstanceIdentifier.class, Bridge.class));
MemberModifier.suppress(MemberMatcher.method(OvsdbBridgeUpdateCommand.class, "bridgeOtherConfigsToRemove",
InstanceIdentifier.class, Bridge.class));
+ MemberModifier.suppress(MemberMatcher.method(OvsdbBridgeUpdateCommand.class, "getNodeId",
+ Bridge.class));
Bridge bridge = mock(Bridge.class);
InstanceIdentifier<Node> connectionIId = mock(InstanceIdentifier.class);
when(dbSchema.getVersion())
.thenReturn(Version.fromString(SouthboundConstants.AUTOATTACH_SUPPORTED_OVS_SCHEMA_VERSION));
OvsdbOperationalCommandAggregator ovsdbOperationalCommandAggregator1 = new OvsdbOperationalCommandAggregator(
- mock(InstanceIdentifierCodec.class), key, updates, dbSchema);
+ mock(InstanceIdentifierCodec.class), key, updates, dbSchema, false);
List<TransactionCommand> testCommands = Whitebox.getInternalState(ovsdbOperationalCommandAggregator1,
"commands");
assertEquals(NUMBER_OF_COMMANDS, testCommands.size());