import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
-import org.opendaylight.netconf.api.ModifyAction;
+import org.opendaylight.netconf.api.EffectiveOperation;
import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceId;
import org.opendaylight.netconf.sal.connect.api.RemoteDeviceServices.Rpcs;
import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfRpcFutureCallback;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
import org.opendaylight.yangtools.rfc8528.data.api.MountPointContext;
import org.opendaylight.yangtools.yang.common.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeService {
+public abstract sealed class AbstractNetconfDataTreeService implements NetconfDataTreeService {
private static final class Candidate extends AbstractNetconfDataTreeService {
- Candidate(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport) {
- super(id, netconfOps, rollbackSupport);
+ Candidate(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport,
+ final boolean lockDatastore) {
+ super(id, netconfOps, rollbackSupport, lockDatastore);
}
/**
@Override
ListenableFuture<? extends DOMRpcResult> editConfig(final DataContainerChild editStructure,
- final ModifyAction defaultOperation) {
+ final EffectiveOperation defaultOperation) {
final NetconfRpcFutureCallback callback = new NetconfRpcFutureCallback("Edit candidate", id);
return defaultOperation == null ? netconfOps.editConfigCandidate(callback, editStructure, rollbackSupport)
: netconfOps.editConfigCandidate(callback, editStructure, defaultOperation, rollbackSupport);
}
private static final class Running extends AbstractNetconfDataTreeService {
- Running(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport) {
- super(id, netconfOps, rollbackSupport);
+ Running(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport,
+ final boolean lockDatastore) {
+ super(id, netconfOps, rollbackSupport, lockDatastore);
}
@Override
return RPC_SUCCESS;
}
+ @Override
+ public ListenableFuture<DOMRpcResult> commit() {
+ // No candidate, hence we commit immediately
+ return RPC_SUCCESS;
+ }
+
@Override
ListenableFuture<? extends DOMRpcResult> lockSingle() {
return netconfOps.lockRunning(new NetconfRpcFutureCallback("Lock running", id));
@Override
ListenableFuture<? extends DOMRpcResult> editConfig(final DataContainerChild editStructure,
- final ModifyAction defaultOperation) {
+ final EffectiveOperation defaultOperation) {
final NetconfRpcFutureCallback callback = new NetconfRpcFutureCallback("Edit running", id);
return defaultOperation == null ? netconfOps.editConfigRunning(callback, editStructure, rollbackSupport)
: netconfOps.editConfigRunning(callback, editStructure, defaultOperation, rollbackSupport);
private final Running running;
CandidateWithRunning(final RemoteDeviceId id, final NetconfBaseOps netconfOps,
- final boolean rollbackSupport) {
- super(id, netconfOps, rollbackSupport);
- candidate = new Candidate(id, netconfOps, rollbackSupport);
- running = new Running(id, netconfOps, rollbackSupport);
+ final boolean rollbackSupport, final boolean lockDatastore) {
+ super(id, netconfOps, rollbackSupport, lockDatastore);
+ candidate = new Candidate(id, netconfOps, rollbackSupport, lockDatastore);
+ running = new Running(id, netconfOps, rollbackSupport, lockDatastore);
}
@Override
@Override
ListenableFuture<? extends DOMRpcResult> editConfig(final DataContainerChild editStructure,
- final ModifyAction defaultOperation) {
+ final EffectiveOperation defaultOperation) {
return candidate.editConfig(editStructure, defaultOperation);
}
}
final NetconfBaseOps netconfOps;
final boolean rollbackSupport;
- // FIXME: what do we do with locks acquired before this got flipped?
- private volatile boolean isLockAllowed = true;
+ private final boolean lockDatastore;
AbstractNetconfDataTreeService(final RemoteDeviceId id, final NetconfBaseOps netconfOps,
- final boolean rollbackSupport) {
+ final boolean rollbackSupport, final boolean lockDatastore) {
this.id = requireNonNull(id);
this.netconfOps = requireNonNull(netconfOps);
this.rollbackSupport = rollbackSupport;
+ this.lockDatastore = lockDatastore;
}
public static @NonNull AbstractNetconfDataTreeService of(final RemoteDeviceId id,
final MountPointContext mountContext, final Rpcs rpcs,
- final NetconfSessionPreferences sessionPreferences) {
+ final NetconfSessionPreferences sessionPreferences, final boolean lockDatastore) {
final var netconfOps = new NetconfBaseOps(rpcs, mountContext);
final boolean rollbackSupport = sessionPreferences.isRollbackSupported();
// Examine preferences and decide which implementation to use
if (sessionPreferences.isCandidateSupported()) {
return sessionPreferences.isRunningWritable()
- ? new CandidateWithRunning(id, netconfOps, rollbackSupport)
- : new Candidate(id, netconfOps, rollbackSupport);
+ ? new CandidateWithRunning(id, netconfOps, rollbackSupport, lockDatastore)
+ : new Candidate(id, netconfOps, rollbackSupport, lockDatastore);
} else if (sessionPreferences.isRunningWritable()) {
- return new Running(id, netconfOps, rollbackSupport);
+ return new Running(id, netconfOps, rollbackSupport, lockDatastore);
} else {
- throw new IllegalArgumentException("Device " + id.getName() + " has advertised neither :writable-running "
- + "nor :candidate capability. Failed to establish session, as at least one of these must be "
- + "advertised.");
+ throw new IllegalArgumentException("Device " + id.name() + " has advertised neither :writable-running nor "
+ + ":candidate capability. Failed to establish session, as at least one of these must be advertised.");
}
}
@Override
public synchronized ListenableFuture<DOMRpcResult> lock() {
- if (!isLockAllowed) {
+ if (!lockDatastore) {
LOG.trace("Lock is not allowed by device configuration, ignoring lock results: {}", id);
return RPC_SUCCESS;
}
final ListenableFuture<DOMRpcResult> result = mergeFutures(lockImpl());
- Futures.addCallback(result, new FutureCallback<DOMRpcResult>() {
+ Futures.addCallback(result, new FutureCallback<>() {
@Override
public void onSuccess(final DOMRpcResult result) {
- final var errors = result.getErrors();
+ final var errors = result.errors();
if (errors.isEmpty()) {
LOG.debug("{}: Lock successful.", id);
return;
@Override
public synchronized ListenableFuture<DOMRpcResult> unlock() {
- // FIXME: deal with lock with lifecycle?
- if (!isLockAllowed) {
+ if (!lockDatastore) {
LOG.trace("Unlock is not allowed: {}", id);
return RPC_SUCCESS;
}
final ListenableFuture<DOMRpcResult> result = mergeFutures(unlockImpl());
- Futures.addCallback(result, new FutureCallback<DOMRpcResult>() {
+ Futures.addCallback(result, new FutureCallback<>() {
@Override
public void onSuccess(final DOMRpcResult result) {
- final var errors = result.getErrors();
+ final var errors = result.errors();
if (errors.isEmpty()) {
LOG.debug("{}: Unlock successful.", id);
return;
@Override
public synchronized ListenableFuture<? extends DOMRpcResult> merge(final LogicalDatastoreType store,
final YangInstanceIdentifier path, final NormalizedNode data,
- final Optional<ModifyAction> defaultOperation) {
+ final Optional<EffectiveOperation> defaultOperation) {
checkEditable(store);
return editConfig(
- netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(ModifyAction.MERGE), path),
+ netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(EffectiveOperation.MERGE),
+ path),
defaultOperation.orElse(null));
}
@Override
public synchronized ListenableFuture<? extends DOMRpcResult> replace(final LogicalDatastoreType store,
final YangInstanceIdentifier path, final NormalizedNode data,
- final Optional<ModifyAction> defaultOperation) {
+ final Optional<EffectiveOperation> defaultOperation) {
checkEditable(store);
return editConfig(
- netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(ModifyAction.REPLACE), path),
+ netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(EffectiveOperation.REPLACE),
+ path),
defaultOperation.orElse(null));
}
@Override
public synchronized ListenableFuture<? extends DOMRpcResult> create(final LogicalDatastoreType store,
final YangInstanceIdentifier path, final NormalizedNode data,
- final Optional<ModifyAction> defaultOperation) {
+ final Optional<EffectiveOperation> defaultOperation) {
checkEditable(store);
return editConfig(
- netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(ModifyAction.CREATE), path),
+ netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(EffectiveOperation.CREATE),
+ path),
defaultOperation.orElse(null));
}
public synchronized ListenableFuture<? extends DOMRpcResult> delete(final LogicalDatastoreType store,
final YangInstanceIdentifier path) {
return editConfig(netconfOps.createEditConfigStructure(Optional.empty(),
- Optional.of(ModifyAction.DELETE), path), null);
+ Optional.of(EffectiveOperation.DELETE), path), null);
}
@Override
public synchronized ListenableFuture<? extends DOMRpcResult> remove(final LogicalDatastoreType store,
final YangInstanceIdentifier path) {
return editConfig(netconfOps.createEditConfigStructure(Optional.empty(),
- Optional.of(ModifyAction.REMOVE), path), null);
+ Optional.of(EffectiveOperation.REMOVE), path), null);
}
@Override
return id;
}
- final void setLockAllowed(final boolean isLockAllowedOrig) {
- isLockAllowed = isLockAllowedOrig;
- }
-
abstract ListenableFuture<? extends DOMRpcResult> editConfig(DataContainerChild editStructure,
- @Nullable ModifyAction defaultOperation);
+ @Nullable EffectiveOperation defaultOperation);
private static void checkEditable(final LogicalDatastoreType store) {
checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can only edit configuration data, not %s", store);
final var builder = ImmutableList.<RpcError>builder();
for (ListenableFuture<? extends DOMRpcResult> future : futures) {
- builder.addAll(Futures.getDone(future).getErrors());
+ builder.addAll(Futures.getDone(future).errors());
}
return new DefaultDOMRpcResult(null, builder.build());
}, MoreExecutors.directExecutor());