package org.opendaylight.controller.sal.connect.netconf.sal;
import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.FluentIterable;
+import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNodeBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(NetconfDeviceDatastoreAdapter.class);
private final RemoteDeviceId id;
- private final DataProviderService dataService;
- private final ListeningExecutorService executor;
+ private final DataBroker dataService;
- NetconfDeviceDatastoreAdapter(final RemoteDeviceId deviceId, final DataProviderService dataService,
- final ExecutorService executor) {
+ NetconfDeviceDatastoreAdapter(final RemoteDeviceId deviceId, final DataBroker dataService) {
this.id = Preconditions.checkNotNull(deviceId);
this.dataService = Preconditions.checkNotNull(dataService);
- this.executor = MoreExecutors.listeningDecorator(Preconditions.checkNotNull(executor));
- // Initial data change scheduled
- submitDataChangeToExecutor(this.executor, new Runnable() {
- @Override
- public void run() {
- initDeviceData();
- }
- }, deviceId);
+ initDeviceData();
}
public void updateDeviceState(final boolean up, final Set<QName> capabilities) {
- submitDataChangeToExecutor(this.executor, new Runnable() {
- @Override
- public void run() {
- updateDeviceStateInternal(up, capabilities);
- }
- }, id);
- }
-
- private void updateDeviceStateInternal(final boolean up, final Set<QName> capabilities) {
final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node data = buildDataForDeviceState(
up, capabilities, id);
- final DataModificationTransaction transaction = dataService.beginTransaction();
- logger.trace("{}: Update device state transaction {} putting operational data started.", id, transaction.getIdentifier());
- transaction.removeOperationalData(id.getBindingPath());
- transaction.putOperationalData(id.getBindingPath(), data);
- logger.trace("{}: Update device state transaction {} putting operational data ended.", id, transaction.getIdentifier());
+ final ReadWriteTransaction transaction = dataService.newReadWriteTransaction();
+ logger.trace("{}: Update device state transaction {} merging operational data started.", id, transaction.getIdentifier());
+ transaction.merge(LogicalDatastoreType.OPERATIONAL, id.getBindingPath(), data);
+ logger.trace("{}: Update device state transaction {} merging operational data ended.", id, transaction.getIdentifier());
commitTransaction(transaction, "update");
}
private void removeDeviceConfigAndState() {
- final DataModificationTransaction transaction = dataService.beginTransaction();
+ final WriteTransaction transaction = dataService.newWriteOnlyTransaction();
logger.trace("{}: Close device state transaction {} removing all data started.", id, transaction.getIdentifier());
- transaction.removeConfigurationData(id.getBindingPath());
- transaction.removeOperationalData(id.getBindingPath());
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, id.getBindingPath());
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, id.getBindingPath());
logger.trace("{}: Close device state transaction {} removing all data ended.", id, transaction.getIdentifier());
commitTransaction(transaction, "close");
}
private void initDeviceData() {
- final DataModificationTransaction transaction = dataService.beginTransaction();
+ final WriteTransaction transaction = dataService.newWriteOnlyTransaction();
- final InstanceIdentifier<Node> path = id.getBindingPath();
+ createNodesListIfNotPresent(transaction);
+ final InstanceIdentifier<Node> path = id.getBindingPath();
final Node nodeWithId = getNodeWithId(id);
- if (operationalNodeNotExisting(transaction, path)) {
- transaction.putOperationalData(path, nodeWithId);
- }
- if (configurationNodeNotExisting(transaction, path)) {
- transaction.putConfigurationData(path, nodeWithId);
- }
- commitTransaction(transaction, "init");
- }
+ logger.trace("{}: Init device state transaction {} putting if absent operational data started.", id, transaction.getIdentifier());
+ transaction.merge(LogicalDatastoreType.OPERATIONAL, path, nodeWithId);
+ logger.trace("{}: Init device state transaction {} putting operational data ended.", id, transaction.getIdentifier());
- private void commitTransaction(final DataModificationTransaction transaction, final String txType) {
- // attempt commit
- final RpcResult<TransactionStatus> result;
- try {
- result = transaction.commit().get();
- } catch (InterruptedException | ExecutionException e) {
- logger.error("{}: Transaction({}) failed", id, txType, e);
- throw new IllegalStateException(id + " Transaction(" + txType + ") not committed correctly", e);
- }
-
- // verify success result + committed state
- if (isUpdateSuccessful(result)) {
- logger.trace("{}: Transaction({}) {} SUCCESSFUL", id, txType, transaction.getIdentifier());
- } else {
- logger.error("{}: Transaction({}) {} FAILED!", id, txType, transaction.getIdentifier());
- throw new IllegalStateException(id + " Transaction(" + txType + ") not committed correctly, " +
- "Errors: " + result.getErrors());
- }
- }
+ logger.trace("{}: Init device state transaction {} putting if absent config data started.", id, transaction.getIdentifier());
+ transaction.merge(LogicalDatastoreType.CONFIGURATION, path, nodeWithId);
+ logger.trace("{}: Init device state transaction {} putting config data ended.", id, transaction.getIdentifier());
- @Override
- public void close() throws Exception {
- // Remove device data from datastore
- submitDataChangeToExecutor(executor, new Runnable() {
- @Override
- public void run() {
- removeDeviceConfigAndState();
- }
- }, id);
+ commitTransaction(transaction, "init");
}
- private static boolean isUpdateSuccessful(final RpcResult<TransactionStatus> result) {
- return result.getResult() == TransactionStatus.COMMITED && result.isSuccessful();
+ private void createNodesListIfNotPresent(final WriteTransaction writeTx) {
+ final Nodes nodes = new NodesBuilder().build();
+ final InstanceIdentifier<Nodes> path = InstanceIdentifier.builder(Nodes.class).build();
+ logger.trace("{}: Merging {} container to ensure its presence", id, Nodes.QNAME, writeTx.getIdentifier());
+ writeTx.merge(LogicalDatastoreType.CONFIGURATION, path, nodes);
+ writeTx.merge(LogicalDatastoreType.OPERATIONAL, path, nodes);
}
- private static void submitDataChangeToExecutor(final ListeningExecutorService executor, final Runnable r,
- final RemoteDeviceId id) {
- // Submit data change
- final ListenableFuture<?> f = executor.submit(r);
- // Verify update execution
- Futures.addCallback(f, new FutureCallback<Object>() {
+ private void commitTransaction(final WriteTransaction transaction, final String txType) {
+ logger.trace("{}: Committing Transaction {}:{}", id, txType, transaction.getIdentifier());
+ final CheckedFuture<Void, TransactionCommitFailedException> result = transaction.submit();
+
+ Futures.addCallback(result, new FutureCallback<Void>() {
@Override
- public void onSuccess(final Object result) {
- logger.debug("{}: Device data updated successfully", id);
+ public void onSuccess(final Void result) {
+ logger.trace("{}: Transaction({}) {} SUCCESSFUL", id, txType, transaction.getIdentifier());
}
@Override
public void onFailure(final Throwable t) {
- logger.warn("{}: Device data update failed", id, t);
+ logger.error("{}: Transaction({}) {} FAILED!", id, txType, transaction.getIdentifier(), t);
+ throw new IllegalStateException(id + " Transaction(" + txType + ") not committed correctly", t);
}
});
+
+ }
+
+ @Override
+ public void close() throws Exception {
+ removeDeviceConfigAndState();
}
public static org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node buildDataForDeviceState(
return nodeBuilder.build();
}
- private static boolean configurationNodeNotExisting(final DataModificationTransaction transaction,
- final InstanceIdentifier<Node> path) {
- return null == transaction.readConfigurationData(path);
- }
-
- private static boolean operationalNodeNotExisting(final DataModificationTransaction transaction,
+ private static ListenableFuture<Optional<Node>> readNodeData(
+ final LogicalDatastoreType store,
+ final ReadWriteTransaction transaction,
final InstanceIdentifier<Node> path) {
- return null == transaction.readOperationalData(path);
+ return transaction.read(store, path);
}
private static Node getNodeWithId(final RemoteDeviceId id) {