<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>utils.southbound-utils</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
this.instanceIdentifier = iid;
}
+ /**
+ * Apply the given command to the given events, based on the given bridge state.
+ *
+ * @param command The command to run.
+ * @param state The current bridge state.
+ * @param events The events to process.
+ */
public void transact(TransactCommand command, BridgeOperationalState state,
AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> events) {
for (TransactInvoker transactInvoker : transactInvokers.values()) {
}
}
+ /**
+ * Apply the given command to the given modifications, based on the given bridge state.
+ *
+ * @param command The command to run.
+ * @param state The current bridge state.
+ * @param modifications The modifications to process.
+ */
+ public void transact(TransactCommand command, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ for (TransactInvoker transactInvoker : transactInvokers.values()) {
+ transactInvoker.invoke(command, state, modifications);
+ }
+ }
+
public void registerCallbacks() {
if ( this.callback == null) {
if (this.initialCreateData != null ) {
--- /dev/null
+/*
+ * Copyright © 2016 Red Hat, Inc. 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;
+
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.southbound.ovsdb.transact.BridgeOperationalState;
+import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactCommandAggregator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+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.node.TerminationPoint;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Data-tree change listener for OVSDB.
+ */
+public class OvsdbDataTreeChangeListener implements ClusteredDataTreeChangeListener<Node>, AutoCloseable {
+
+ /** Our registration. */
+ private final ListenerRegistration<DataTreeChangeListener<Node>> registration;
+
+ /** The connection manager. */
+ private final OvsdbConnectionManager cm;
+
+ /** The data broker. */
+ private final DataBroker db;
+
+ /** Logger. */
+ private static final Logger LOG = LoggerFactory.getLogger(OvsdbDataTreeChangeListener.class);
+
+ /**
+ * Create an instance and register the listener.
+ *
+ * @param db The data broker.
+ * @param cm The connection manager.
+ */
+ OvsdbDataTreeChangeListener(DataBroker db, OvsdbConnectionManager cm) {
+ LOG.info("Registering OvsdbNodeDataChangeListener");
+ this.cm = cm;
+ this.db = db;
+ InstanceIdentifier<Node> path = InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+ .child(Node.class);
+ DataTreeIdentifier<Node> dataTreeIdentifier =
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, path);
+ registration = db.registerDataTreeChangeListener(dataTreeIdentifier, this);
+ }
+
+ @Override
+ public void close() {
+ registration.close();
+ }
+
+ @Override
+ public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> changes) {
+ LOG.trace("onDataTreeChanged: {}", changes);
+
+ // Connect first if necessary
+ connect(changes);
+
+ // Update connections if necessary
+ updateConnections(changes);
+
+ // Update the actual data
+ updateData(changes);
+
+ // Disconnect if necessary
+ disconnect(changes);
+
+ LOG.trace("onDataTreeChanged: exit");
+ }
+
+ private void connect(@Nonnull Collection<DataTreeModification<Node>> changes) {
+ for (DataTreeModification<Node> change : changes) {
+ if (change.getRootNode().getModificationType() == DataObjectModification.ModificationType.WRITE || change
+ .getRootNode().getModificationType() == DataObjectModification.ModificationType.SUBTREE_MODIFIED) {
+ DataObjectModification<OvsdbNodeAugmentation> ovsdbNodeModification =
+ change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class);
+ if (ovsdbNodeModification != null && ovsdbNodeModification.getDataBefore() == null
+ && ovsdbNodeModification.getDataAfter() != null) {
+ OvsdbNodeAugmentation ovsdbNode = ovsdbNodeModification.getDataAfter();
+ ConnectionInfo key = ovsdbNode.getConnectionInfo();
+ InstanceIdentifier<Node> iid = cm.getInstanceIdentifier(key);
+ if ( iid != null) {
+ LOG.warn("Connection to device {} already exists. Plugin does not allow multiple connections "
+ + "to same device, hence dropping the request {}", key, ovsdbNode);
+ } else {
+ try {
+ InstanceIdentifier<Node> instanceIdentifier = change.getRootPath().getRootIdentifier();
+ LOG.info("Connecting on key {} to {}", instanceIdentifier, ovsdbNode);
+ cm.connect(instanceIdentifier, ovsdbNode);
+ } catch (UnknownHostException e) {
+ LOG.warn("Failed to connect to ovsdbNode", e);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void disconnect(@Nonnull Collection<DataTreeModification<Node>> changes) {
+ for (DataTreeModification<Node> change : changes) {
+ if (change.getRootNode().getModificationType() == DataObjectModification.ModificationType.DELETE) {
+ DataObjectModification<OvsdbNodeAugmentation> ovsdbNodeModification =
+ change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class);
+ if (ovsdbNodeModification != null && ovsdbNodeModification.getDataBefore() != null) {
+ OvsdbNodeAugmentation ovsdbNode = ovsdbNodeModification.getDataBefore();
+ ConnectionInfo key = ovsdbNode.getConnectionInfo();
+ InstanceIdentifier<Node> iid = cm.getInstanceIdentifier(key);
+ try {
+ LOG.info("Disconnecting from {}", ovsdbNode);
+ cm.disconnect(ovsdbNode);
+ cm.stopConnectionReconciliationIfActive(iid.firstIdentifierOf(Node.class), ovsdbNode);
+ } catch (UnknownHostException e) {
+ LOG.warn("Failed to disconnect ovsdbNode", e);
+ }
+ }
+ }
+ }
+ }
+
+ private void updateConnections(@Nonnull Collection<DataTreeModification<Node>> changes) {
+ for (DataTreeModification<Node> change : changes) {
+ if (change.getRootNode().getModificationType() == DataObjectModification.ModificationType.WRITE || change
+ .getRootNode().getModificationType() == DataObjectModification.ModificationType.SUBTREE_MODIFIED) {
+ DataObjectModification<OvsdbNodeAugmentation> ovsdbNodeModification =
+ change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class);
+ if (ovsdbNodeModification != null && ovsdbNodeModification.getDataBefore() != null
+ && ovsdbNodeModification.getDataAfter() != null) {
+ OvsdbClient client = cm.getClient(ovsdbNodeModification.getDataAfter().getConnectionInfo());
+ if (client == null) {
+ if (ovsdbNodeModification.getDataBefore() != null) {
+ try {
+ cm.disconnect(ovsdbNodeModification.getDataBefore());
+ cm.connect(change.getRootPath().getRootIdentifier(), ovsdbNodeModification
+ .getDataAfter());
+ } catch (UnknownHostException e) {
+ LOG.warn("Error disconnecting from or connecting to ovsdbNode", e);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void updateData(@Nonnull Collection<DataTreeModification<Node>> changes) {
+ for (Entry<InstanceIdentifier<Node>, OvsdbConnectionInstance> connectionInstanceEntry :
+ connectionInstancesFromChanges(changes).entrySet()) {
+ OvsdbConnectionInstance connectionInstance = connectionInstanceEntry.getValue();
+ connectionInstance.transact(new TransactCommandAggregator(),
+ new BridgeOperationalState(db, changes), changes);
+ }
+ }
+
+ private Map<InstanceIdentifier<Node>, OvsdbConnectionInstance> connectionInstancesFromChanges(
+ @Nonnull Collection<DataTreeModification<Node>> changes) {
+ Map<InstanceIdentifier<Node>,OvsdbConnectionInstance> result =
+ new HashMap<>();
+ for (DataTreeModification<Node> change : changes) {
+ DataObjectModification<OvsdbBridgeAugmentation> bridgeModification =
+ change.getRootNode().getModifiedAugmentation(OvsdbBridgeAugmentation.class);
+ OvsdbConnectionInstance client = null;
+ Node node = change.getRootNode().getDataAfter();
+ if (bridgeModification != null && bridgeModification.getDataAfter() != null) {
+ client = cm.getConnectionInstance(bridgeModification.getDataAfter());
+ } else {
+ DataObjectModification<OvsdbNodeAugmentation> nodeModification =
+ change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class);
+ if (nodeModification != null && nodeModification.getDataAfter() != null && nodeModification
+ .getDataAfter().getConnectionInfo() != null) {
+ client = cm.getConnectionInstance(nodeModification.getDataAfter().getConnectionInfo());
+ } else {
+ if (node != null) {
+ List<TerminationPoint> terminationPoints = node.getTerminationPoint();
+ if (terminationPoints != null && !terminationPoints.isEmpty()) {
+ InstanceIdentifier<Node> nodeIid = SouthboundMapper.createInstanceIdentifier(
+ node.getNodeId());
+ client = cm.getConnectionInstance(nodeIid);
+ }
+ }
+ }
+ }
+ if (client != null) {
+ LOG.debug("Found client for {}", node);
+ /*
+ * As of now data change sets are processed by single thread, so we can assume that device will
+ * be connected and ownership will be decided before sending any instructions down to the device.
+ * Note:Processing order in onDataChange() method should not change. If processing is changed to
+ * use multiple thread, we might need to take care of corner cases, where ownership is not decided
+ * but transaction are ready to go to switch. In that scenario, either we need to queue those task
+ * till ownership is decided for that specific device.
+ * Given that each DataChangeNotification is notified through separate thread, so we are already
+ * multi threaded and i don't see any need to further parallelism per DataChange
+ * notifications processing.
+ */
+ if ( cm.getHasDeviceOwnership(client.getMDConnectionInfo())) {
+ LOG.debug("*This* instance of southbound plugin is an owner of the device {}", node);
+ result.put(change.getRootPath().getRootIdentifier(), client);
+ } else {
+ LOG.debug("*This* instance of southbound plugin is *not* an owner of the device {}", node);
+ }
+ } else {
+ LOG.debug("Did not find client for {}", node);
+ }
+ }
+ return result;
+ }
+}
private static DataBroker db;
private OvsdbConnectionManager cm;
private TransactionInvoker txInvoker;
- private OvsdbDataChangeListener ovsdbDataChangeListener;
+ private OvsdbDataTreeChangeListener ovsdbDataTreeChangeListener;
private EntityOwnershipService entityOwnershipService;
private EntityOwnershipCandidateRegistration registration;
private SouthboundPluginInstanceEntityOwnershipListener providerOwnershipChangeListener;
db = session.getSALService(DataBroker.class);
this.txInvoker = new TransactionInvokerImpl(db);
cm = new OvsdbConnectionManager(db,txInvoker,entityOwnershipService, ovsdbConnection);
- ovsdbDataChangeListener = new OvsdbDataChangeListener(db,cm);
+ ovsdbDataTreeChangeListener = new OvsdbDataTreeChangeListener(db, cm);
//Register listener for entityOnwership changes
providerOwnershipChangeListener =
public void close() {
LOG.info("SouthboundProvider Closed");
cm.close();
- ovsdbDataChangeListener.close();
+ ovsdbDataTreeChangeListener.close();
registration.close();
providerOwnershipChangeListener.close();
}
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
public class AutoAttachRemovedCommand implements TransactCommand {
private static final Logger LOG = LoggerFactory.getLogger(AutoAttachRemovedCommand.class);
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractOriginal(modifications, OvsdbNodeAugmentation.class),
+ TransactUtils.extractUpdated(modifications, OvsdbNodeAugmentation.class));
+ }
+
@Override
public void execute(TransactionBuilder transaction, BridgeOperationalState state,
AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> events) {
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> createdOrUpdated) {
package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
transaction.close();
}
+ public BridgeOperationalState(DataBroker db, Collection<DataTreeModification<Node>> changes) {
+ ReadOnlyTransaction transaction = db.newReadOnlyTransaction();
+ Map<InstanceIdentifier<Node>, Node> nodeCreateOrUpdateOrRemove =
+ TransactUtils.extractCreatedOrUpdatedOrRemoved(changes, Node.class);
+ for (Entry<InstanceIdentifier<Node>, Node> entry : nodeCreateOrUpdateOrRemove.entrySet()) {
+ try {
+ Optional<Node> nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, entry.getKey())
+ .checkedGet();
+ if (nodeOptional.isPresent()) {
+ operationalNodes.put(entry.getKey(), nodeOptional.get());
+ }
+ } catch (ReadFailedException e) {
+ LOG.warn("Error reading from datastore", e);
+ }
+ }
+ }
+
public Optional<Node> getBridgeNode(InstanceIdentifier<?> iid) {
InstanceIdentifier<Node> nodeIid = iid.firstIdentifierOf(Node.class);
return Optional.fromNullable(operationalNodes.get(nodeIid));
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
TransactUtils.extractOriginal(events, OvsdbBridgeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractRemoved(modifications, OvsdbBridgeAugmentation.class),
+ TransactUtils.extractOriginal(modifications, OvsdbBridgeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state, Set<InstanceIdentifier<OvsdbBridgeAugmentation>> removed,
Map<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> originals) {
for (InstanceIdentifier<OvsdbBridgeAugmentation> ovsdbManagedNodeIid: removed) {
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.Insert;
execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbBridgeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state,
+ TransactUtils.extractCreatedOrUpdated(modifications, OvsdbBridgeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> createdOrUpdated) {
for (Entry<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> ovsdbManagedNodeEntry :
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
TransactUtils.extractCreatedOrUpdatedOrRemoved(events, OvsdbBridgeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractRemoved(modifications, ControllerEntry.class),
+ TransactUtils.extractCreatedOrUpdatedOrRemoved(modifications, OvsdbBridgeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Set<InstanceIdentifier<ControllerEntry>> removedControllers,
Map<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation>
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.southbound.SouthboundMapper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
TransactUtils.extractCreatedOrUpdated(events, OvsdbBridgeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, ControllerEntry.class),
+ TransactUtils.extractCreatedOrUpdated(modifications, OvsdbBridgeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<ControllerEntry>, ControllerEntry> controllers,
Map<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> bridges) {
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.lib.operations.Insert;
import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
import com.google.common.collect.Sets;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
execute(transaction);
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction);
+ }
+
private void execute(TransactionBuilder transaction) {
Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Bridge.class);
List<Insert> inserts = TransactUtils.extractInsert(transaction, bridge.getSchema());
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.lib.operations.Mutate;
execute(transaction, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated) {
for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry:
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
TransactUtils.extractCreatedOrUpdatedOrRemoved(events, OvsdbBridgeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractRemoved(modifications, ProtocolEntry.class),
+ TransactUtils.extractCreatedOrUpdatedOrRemoved(modifications, OvsdbBridgeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state, Set<InstanceIdentifier<ProtocolEntry>> removed,
Map<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> updatedBridges) {
for (InstanceIdentifier<ProtocolEntry> protocolIid : removed) {
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
TransactUtils.extractCreatedOrUpdated(events, OvsdbBridgeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, ProtocolEntry.class),
+ TransactUtils.extractCreatedOrUpdated(modifications, OvsdbBridgeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<ProtocolEntry>, ProtocolEntry> protocols,
Map<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> bridges) {
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
TransactUtils.extractUpdated(events, OvsdbNodeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state,
+ TransactUtils.extractOriginal(modifications, OvsdbNodeAugmentation.class),
+ TransactUtils.extractUpdated(modifications, OvsdbNodeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originals,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated) {
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> createdOrUpdated) {
for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry:
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
TransactUtils.extractUpdated(events, OvsdbNodeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractOriginal(modifications, OvsdbNodeAugmentation.class),
+ TransactUtils.extractUpdated(modifications, OvsdbNodeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originals,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated) {
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> createdOrUpdated) {
for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry:
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.ExecutionException;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
TransactUtils.extractCreatedOrUpdated(events, Node.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state, TransactUtils.extractCreated(modifications, OvsdbTerminationPointAugmentation.class),
+ TransactUtils.extractCreatedOrUpdated(modifications, Node.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>,
OvsdbTerminationPointAugmentation>
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.lib.notation.UUID;
TransactUtils.extractRemoved(events, OvsdbTerminationPointAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction, state,
+ TransactUtils.extractOriginal(modifications, OvsdbTerminationPointAugmentation.class),
+ TransactUtils.extractOriginal(modifications, Node.class),
+ TransactUtils.extractRemoved(modifications, OvsdbTerminationPointAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction, BridgeOperationalState state,
Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation> originals,
Map<InstanceIdentifier<Node>, Node> originalNodes,
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
execute(transaction, TransactUtils.extractCreatedOrUpdated(events, OvsdbTerminationPointAugmentation.class));
}
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ execute(transaction,
+ TransactUtils.extractCreatedOrUpdated(modifications, OvsdbTerminationPointAugmentation.class));
+ }
+
private void execute(TransactionBuilder transaction,
Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>,
OvsdbTerminationPointAugmentation> createdOrUpdated) {
*/
package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
*/
void execute(TransactionBuilder transaction, BridgeOperationalState state,
AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> events);
+
+ /**
+ * Queue the command defined by the class implementing this interface in the given transaction builder, with the
+ * given bridge state, in reaction to the given modifications.
+ *
+ * @param transaction The transaction builder.
+ * @param state The bridge state.
+ * @param modifications The modifications to be represented.
+ */
+ void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications);
}
*/
package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
}
}
}
+
+ @Override
+ public void execute(TransactionBuilder transaction, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ for (Class<? extends TransactCommand> commandClass : COMMAND_CLASSES) {
+ try {
+ commandClass.newInstance().execute(transaction, state, modifications);
+ } catch (InstantiationException | IllegalAccessException e) {
+ LOG.error("Error instantiating {}", commandClass, e);
+ }
+ }
+ }
}
*/
package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
*/
void invoke(TransactCommand command, BridgeOperationalState state,
AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> events);
+
+ /**
+ * Invoke the given transactional command, with the given bridge state, on the given modifications.
+ *
+ * @param command The transactional command.
+ * @param state The bridge state.
+ * @param modifications The modifications to be processed.
+ */
+ void invoke(TransactCommand command, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications);
}
*/
package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+import java.util.Collection;
import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.operations.OperationResult;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
invoke(command, tb);
}
+ @Override
+ public void invoke(TransactCommand command, BridgeOperationalState state,
+ Collection<DataTreeModification<Node>> modifications) {
+ TransactionBuilder tb = new TransactionBuilder(connectionInstance, dbSchema);
+ command.execute(tb, state, modifications);
+ invoke(command, tb);
+ }
+
private void invoke(TransactCommand command, TransactionBuilder tb) {
ListenableFuture<List<OperationResult>> result = tb.execute();
LOG.debug("invoke: command: {}, tb: {}", command, tb);
import static org.opendaylight.ovsdb.lib.operations.Operations.op;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Queue;
import java.util.Set;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Predicate;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.ovsdb.lib.notation.Mutation;
import org.opendaylight.ovsdb.lib.notation.Mutator;
import org.opendaylight.ovsdb.southbound.SouthboundMapper;
import org.opendaylight.ovsdb.southbound.SouthboundUtil;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+
+import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TransactUtils {
private static final Logger LOG = LoggerFactory.getLogger(TransactUtils.class);
+ private static <T extends DataObject> Predicate<DataObjectModification<T>> hasDataBefore() {
+ return new Predicate<DataObjectModification<T>>() {
+ @Override
+ public boolean apply(@Nullable DataObjectModification<T> input) {
+ return input != null && input.getDataBefore() != null;
+ }
+ };
+ }
+
+ private static <T extends DataObject> Predicate<DataObjectModification<T>> hasDataBeforeAndDataAfter() {
+ return new Predicate<DataObjectModification<T>>() {
+ @Override
+ public boolean apply(@Nullable DataObjectModification<T> input) {
+ return input != null && input.getDataBefore() != null && input.getDataAfter() != null;
+ }
+ };
+ }
+
+ private static <T extends DataObject> Predicate<DataObjectModification<T>> hasNoDataBefore() {
+ return new Predicate<DataObjectModification<T>>() {
+ @Override
+ public boolean apply(@Nullable DataObjectModification<T> input) {
+ return input != null && input.getDataBefore() == null;
+ }
+ };
+ }
+
+ private static <T extends DataObject> Predicate<DataObjectModification<T>> hasDataAfterAndMatchesFilter(
+ final Predicate<DataObjectModification<T>> filter) {
+ return new Predicate<DataObjectModification<T>>() {
+ @Override
+ public boolean apply(@Nullable DataObjectModification<T> input) {
+ return input != null && input.getDataAfter() != null && filter.apply(input);
+ }
+ };
+ }
+
+ private static <T extends DataObject> Predicate<DataObjectModification<T>> matchesEverything() {
+ return new Predicate<DataObjectModification<T>>() {
+ @Override
+ public boolean apply(@Nullable DataObjectModification<T> input) {
+ return true;
+ }
+ };
+ }
+
+ private static <T extends DataObject> Predicate<DataObjectModification<T>> modificationIsDeletion() {
+ return new Predicate<DataObjectModification<T>>() {
+ @Override
+ public boolean apply(@Nullable DataObjectModification<T> input) {
+ return input != null && input.getModificationType() == DataObjectModification
+ .ModificationType.DELETE;
+ }
+ };
+ }
+
+ private static <T extends DataObject> Predicate<DataObjectModification<T>> modificationIsDeletionAndHasDataBefore
+ () {
+ return new Predicate<DataObjectModification<T>>() {
+ @Override
+ public boolean apply(@Nullable DataObjectModification<T> input) {
+ return input != null && input.getModificationType() == DataObjectModification
+ .ModificationType.DELETE && input.getDataBefore() != null;
+ }
+ };
+ }
+
public static Map<InstanceIdentifier<Node>,Node> extractNode(
Map<InstanceIdentifier<?>, DataObject> changes) {
Map<InstanceIdentifier<Node>,Node> result
return extract(changes.getCreatedData(),klazz);
}
+ /**
+ * Extract all the instances of {@code clazz} which were created in the given set of modifications.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The created instances, mapped by instance identifier.
+ */
+ public static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, T> extractCreated(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz) {
+ return extractCreatedOrUpdated(changes, clazz, hasNoDataBefore());
+ }
+
+ /**
+ * Extract all the instance of {@code clazz} which were created or updated in the given set of modifications, and
+ * which satisfy the given filter.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param filter The filter the changes must satisfy.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The created or updated instances which satisfy the filter, mapped by instance identifier.
+ */
+ public static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, T> extractCreatedOrUpdated(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz,
+ Predicate<DataObjectModification<T>> filter) {
+ Map<InstanceIdentifier<T>, T> result = new HashMap<>();
+ for (Map.Entry<InstanceIdentifier<T>, DataObjectModification<T>> entry : extractDataObjectModifications(changes,
+ clazz, hasDataAfterAndMatchesFilter(filter)).entrySet()) {
+ result.put(entry.getKey(), entry.getValue().getDataAfter());
+ }
+ return result;
+ }
+
public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extractUpdated(
AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
return extract(changes.getUpdatedData(),klazz);
}
+ /**
+ * Extract all the instances of {@code clazz} which were updated in the given set of modifications.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The updated instances, mapped by instance identifier.
+ */
+ public static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, T> extractUpdated(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz) {
+ return extractCreatedOrUpdated(changes, clazz, hasDataBeforeAndDataAfter());
+ }
+
public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extractCreatedOrUpdated(
AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
Map<InstanceIdentifier<T>,T> result = extractUpdated(changes,klazz);
return result;
}
+ /**
+ * Extract all the instances of {@code clazz} which were created or updated in the given set of modifications.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The created or updated instances, mapped by instance identifier.
+ */
+ public static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, T> extractCreatedOrUpdated(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz) {
+ return extractCreatedOrUpdated(changes, clazz, matchesEverything());
+ }
+
public static <T extends DataObject> Map<InstanceIdentifier<T>, T> extractCreatedOrUpdatedOrRemoved(
AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
Class<T> klazz) {
return result;
}
+ /**
+ * Extract all the instances of {@code clazz} which were created, updated, or removed in the given set of
+ * modifications. For instances which were created or updated, the new instances are returned; for instances
+ * which were removed, the old instances are returned.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The created, updated or removed instances, mapped by instance identifier.
+ */
+ public static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, T>
+ extractCreatedOrUpdatedOrRemoved(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz) {
+ Map<InstanceIdentifier<T>, T> result = extractCreatedOrUpdated(changes, clazz);
+ result.putAll(extractRemovedObjects(changes, clazz));
+ return result;
+ }
+
public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extractOriginal(
AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
return extract(changes.getOriginalData(),klazz);
}
+ /**
+ * Extract the original instances of class {@code clazz} in the given set of modifications.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The original instances, mapped by instance identifier.
+ */
+ public static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, T> extractOriginal(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz) {
+ Map<InstanceIdentifier<T>, T> result = new HashMap<>();
+ for (Map.Entry<InstanceIdentifier<T>, DataObjectModification<T>> entry :
+ extractDataObjectModifications(changes, clazz, hasDataBefore()).entrySet()) {
+ result.put(entry.getKey(), entry.getValue().getDataBefore());
+ }
+ return result;
+ }
+
public static <T extends DataObject> Set<InstanceIdentifier<T>> extractRemoved(
AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
Set<InstanceIdentifier<T>> result = new HashSet<>();
return result;
}
+ /**
+ * Extract the instance identifier of removed instances of {@code clazz} from the given set of modifications.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The instance identifiers of removed instances.
+ */
+ public static <T extends DataObject, U extends DataObject> Set<InstanceIdentifier<T>> extractRemoved(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz) {
+ return extractDataObjectModifications(changes, clazz, modificationIsDeletion()).keySet();
+ }
+
+ /**
+ * Extract all the modifications affecting instances of {@code clazz} which are present in the given set of
+ * modifications and satisfy the given filter.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param filter The filter the changes must satisfy.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The modifications, mapped by instance identifier.
+ */
+ private static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, DataObjectModification<T>>
+ extractDataObjectModifications(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz,
+ Predicate<DataObjectModification<T>> filter) {
+ List<DataObjectModification<? extends DataObject>> dataObjectModifications = new ArrayList<>();
+ List<InstanceIdentifier<? extends DataObject>> paths = new ArrayList<>();
+ if (changes != null) {
+ for (DataTreeModification<? extends DataObject> change : changes) {
+ dataObjectModifications.add(change.getRootNode());
+ paths.add(change.getRootPath().getRootIdentifier());
+ }
+ }
+ return extractDataObjectModifications(dataObjectModifications, paths, clazz, filter);
+ }
+
+ /**
+ * Extract all the modifications affecting instances of {@code clazz} which are present in the given set of
+ * modifications and satisfy the given filter.
+ *
+ * @param changes The changes to process.
+ * @param paths The paths of the changes.
+ * @param clazz The class we're interested in.
+ * @param filter The filter the changes must satisfy.
+ * @param <T> The type of changes we're interested in.
+ * @return The modifications, mapped by instance identifier.
+ */
+ private static <T extends DataObject> Map<InstanceIdentifier<T>, DataObjectModification<T>>
+ extractDataObjectModifications(
+ Collection<DataObjectModification<? extends DataObject>> changes,
+ Collection<InstanceIdentifier<? extends DataObject>> paths, Class<T> clazz,
+ Predicate<DataObjectModification<T>> filter) {
+ Map<InstanceIdentifier<T>, DataObjectModification<T>> result = new HashMap<>();
+ Queue<DataObjectModification<? extends DataObject>> remainingChanges = new LinkedList<>(changes);
+ Queue<InstanceIdentifier<? extends DataObject>> remainingPaths = new LinkedList<>(paths);
+ while (!remainingChanges.isEmpty()) {
+ DataObjectModification<? extends DataObject> change = remainingChanges.remove();
+ InstanceIdentifier<? extends DataObject> path = remainingPaths.remove();
+ // Is the change relevant?
+ if (clazz.isAssignableFrom(change.getDataType()) && filter.apply((DataObjectModification<T>) change)) {
+ result.put((InstanceIdentifier<T>) path, (DataObjectModification<T>) change);
+ }
+ // Add any children to the queue
+ for (DataObjectModification<? extends DataObject> child : change.getModifiedChildren()) {
+ remainingChanges.add(child);
+ remainingPaths.add(extendPath(path, child));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Extends the given instance identifier path to include the given child. Augmentations are treated in the same way
+ * as children; keyed children are handled correctly.
+ *
+ * @param path The current path.
+ * @param child The child modification to include.
+ * @return The extended path.
+ */
+ private static <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>, T extends DataObject>
+ InstanceIdentifier<? extends DataObject> extendPath(
+ InstanceIdentifier path,
+ DataObjectModification child) {
+ Class<N> item = (Class<N>) child.getDataType();
+ if (child.getIdentifier() instanceof InstanceIdentifier.IdentifiableItem) {
+ K key = (K) ((InstanceIdentifier.IdentifiableItem) child.getIdentifier()).getKey();
+ KeyedInstanceIdentifier<N, K> extendedPath = path.child(item, key);
+ LOG.debug("Building a new child iid for {} with {} and key {}, resulting in {}",
+ path, item, extendedPath);
+ return extendedPath;
+ } else {
+ InstanceIdentifier<N> extendedPath = path.child(item);
+ LOG.debug("Building a new child iid for {} with {}, resulting in {}",
+ path, item, extendedPath);
+ return extendedPath;
+ }
+ }
+
public static <T extends DataObject> Map<InstanceIdentifier<T>, T> extractRemovedObjects(
AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
Class<T> klazz) {
return Maps.filterKeys(extractOriginal(changes, klazz),Predicates.in(iids));
}
+ /**
+ * Extract the removed instances of {@code clazz} from the given set of modifications.
+ *
+ * @param changes The changes to process.
+ * @param clazz The class we're interested in.
+ * @param <T> The type of changes we're interested in.
+ * @param <U> The type of changes to process.
+ * @return The removed instances, keyed by instance identifier.
+ */
+ public static <T extends DataObject, U extends DataObject> Map<InstanceIdentifier<T>, T> extractRemovedObjects(
+ Collection<DataTreeModification<U>> changes, Class<T> clazz) {
+ Map<InstanceIdentifier<T>, T> result = new HashMap<>();
+ for (Map.Entry<InstanceIdentifier<T>, DataObjectModification<T>> entry :
+ extractDataObjectModifications(changes, clazz, modificationIsDeletionAndHasDataBefore()).entrySet()) {
+ result.put(entry.getKey(), entry.getValue().getDataBefore());
+ }
+ return result;
+ }
+
public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extract(
Map<InstanceIdentifier<?>, DataObject> changes, Class<T> klazz) {
Map<InstanceIdentifier<T>,T> result = new HashMap<>();
any(InstanceIdentifier.class),
any(AsyncDataChangeEvent.class)).thenReturn(dataChangesManagedByOvsdbNodeEvent);
- PowerMockito.whenNew(BridgeOperationalState.class).withArguments(any(DataBroker.class), any(AsyncDataChangeEvent.class)).thenReturn(bridgeOperationalState);
+ PowerMockito.whenNew(BridgeOperationalState.class.getConstructor(DataBroker.class,
+ AsyncDataChangeEvent.class)).withArguments(any(DataBroker.class),
+ any(AsyncDataChangeEvent.class)).thenReturn(bridgeOperationalState);
when(connectionInstance.getInstanceIdentifier()).thenReturn(iid);
doNothing().when(connectionInstance).transact(any(TransactCommandAggregator.class), eq(bridgeOperationalState),
--- /dev/null
+/*
+ * Copyright © 2016 Red Hat, Inc. and others.
+ *
+ * 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;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.OvsdbConnection;
+import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvokerImpl;
+import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes
+ .ConnectionInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology
+ .Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Unit tests for the data-tree change listener.
+ */
+public class OvsdbDataTreeChangeListenerTest extends AbstractDataBrokerTest {
+ private final OvsdbConnection ovsdbConnection = Mockito.mock(OvsdbConnection.class);
+ private DataBroker dataBroker;
+ private OvsdbDataTreeChangeListener listener;
+
+ @Before
+ public void setupListener() {
+ dataBroker = getDataBroker();
+ EntityOwnershipService entityOwnershipService = Mockito.mock(EntityOwnershipService.class);
+ listener = new OvsdbDataTreeChangeListener(dataBroker,
+ new OvsdbConnectionManager(dataBroker, new TransactionInvokerImpl(dataBroker), entityOwnershipService,
+ ovsdbConnection));
+ }
+
+ @Test
+ public void testConnect() throws UnknownHostException, InterruptedException, ExecutionException {
+ // Given ...
+
+ // When we request a connection ...
+ InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
+ int port = 6640;
+ IpAddress ipAddress = SouthboundMapper.createIpAddress(inetAddress);
+ PortNumber portNumber = new PortNumber(port);
+
+ final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
+ .setRemoteIp(ipAddress)
+ .setRemotePort(portNumber)
+ .build();
+ final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, SouthboundUtils.createNode(connectionInfo),
+ WriteTransaction.CREATE_MISSING_PARENTS);
+ transaction.submit().get();
+
+ // Then the listener tries to open a connection
+ Mockito.verify(ovsdbConnection).connect(inetAddress, port);
+ }
+}