import static java.util.Objects.requireNonNull;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
+import java.util.Base64;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.aaa.encrypt.AAAEncryptionService;
import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.RpcProviderService;
import org.opendaylight.mdsal.binding.api.WriteTransaction;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.Credentials;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.LoginPw;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.LoginPwBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.login.pw.LoginPasswordBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.CreateDeviceInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.CreateDeviceOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.CreateDeviceOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.DeleteDeviceInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.DeleteDeviceOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.DeleteDeviceOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeTopologyService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.Credentials;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.KeyAuthBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.LoginPwBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.LoginPwUnencryptedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.key.auth.KeyBasedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.login.pw.LoginPasswordBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencryptedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.optional.rev221225.NetconfNodeAugmentedOptionalBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.CreateDevice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.CreateDeviceInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.CreateDeviceOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.CreateDeviceOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.DeleteDevice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.DeleteDeviceInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.DeleteDeviceOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.DeleteDeviceOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.rpc.credentials.RpcCredentials;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.rpc.credentials.rpc.credentials.KeyAuth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.rpc.credentials.rpc.credentials.LoginPw;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.rpc.credentials.rpc.credentials.LoginPwUnencrypted;
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.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
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.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Rpc;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Deprecated
-public class NetconfTopologyRPCProvider implements NetconfNodeTopologyService {
+public final class NetconfTopologyRPCProvider implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyRPCProvider.class);
private final @NonNull InstanceIdentifier<Topology> topologyPath;
private final @NonNull AAAEncryptionService encryptionService;
private final @NonNull DataBroker dataBroker;
- public NetconfTopologyRPCProvider(final DataBroker dataBroker, final AAAEncryptionService encryptionService,
- final String topologyId) {
+ private final Registration reg;
+
+ public NetconfTopologyRPCProvider(final RpcProviderService rpcProviderService, final DataBroker dataBroker,
+ final AAAEncryptionService encryptionService, final String topologyId) {
this.dataBroker = requireNonNull(dataBroker);
this.encryptionService = requireNonNull(encryptionService);
topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
- .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
- .build();
+ .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
+ .build();
+ reg = rpcProviderService.registerRpcImplementations(ImmutableClassToInstanceMap.<Rpc<?, ?>>builder()
+ .put(CreateDevice.class, this::createDevice)
+ .put(DeleteDevice.class, this::deleteDevice)
+ .build());
}
- protected final @NonNull InstanceIdentifier<Topology> topologyPath() {
+ protected @NonNull InstanceIdentifier<Topology> topologyPath() {
return topologyPath;
}
@Override
- public final ListenableFuture<RpcResult<CreateDeviceOutput>> createDevice(final CreateDeviceInput input) {
- final NetconfNode node = encryptPassword(input);
+ public void close() {
+ reg.close();
+ }
+
+ private ListenableFuture<RpcResult<CreateDeviceOutput>> createDevice(final CreateDeviceInput input) {
+ final var netconfNode = encryptPassword(input);
+ final var nodeId = new NodeId(input.getNodeId());
+ final var nodeBuilder = new NodeBuilder()
+ .setNodeId(nodeId)
+ .addAugmentation(netconfNode);
+ if (input.getIgnoreMissingSchemaSources() != null) {
+ final var netconfNodeOptionalBuilder = new NetconfNodeAugmentedOptionalBuilder(input);
+ nodeBuilder.addAugmentation(netconfNodeOptionalBuilder.build());
+ }
final SettableFuture<RpcResult<CreateDeviceOutput>> futureResult = SettableFuture.create();
- final NodeId nodeId = new NodeId(input.getNodeId());
- writeToConfigDS(node, nodeId, futureResult);
+ writeToConfigDS(nodeBuilder.build(), nodeId, futureResult);
return futureResult;
}
- @Override
- public final ListenableFuture<RpcResult<DeleteDeviceOutput>> deleteDevice(final DeleteDeviceInput input) {
+ private ListenableFuture<RpcResult<DeleteDeviceOutput>> deleteDevice(final DeleteDeviceInput input) {
final NodeId nodeId = new NodeId(input.getNodeId());
final InstanceIdentifier<Node> niid = topologyPath.child(Node.class, new NodeKey(nodeId));
NetconfNode encryptPassword(final CreateDeviceInput input) {
final NetconfNodeBuilder builder = new NetconfNodeBuilder();
builder.fieldsFrom(input);
-
- return builder.setCredentials(handleEncryption(input.getCredentials()))
+ return builder.setCredentials(translate(input.getRpcCredentials()))
.build();
}
- private Credentials handleEncryption(final Credentials credentials) {
- if (credentials instanceof LoginPw loginPw) {
+ private Credentials translate(final RpcCredentials credentialsRpc) {
+ if (credentialsRpc instanceof LoginPw loginPw) {
final var loginPassword = loginPw.getLoginPassword();
-
return new LoginPwBuilder()
.setLoginPassword(new LoginPasswordBuilder()
.setUsername(loginPassword.getUsername())
- .setPassword(encryptionService.encrypt(loginPassword.getPassword()))
+ .setPassword(Base64.getDecoder().decode(encryptionService.encrypt(loginPassword.getPassword())))
.build())
.build();
+ } else if (credentialsRpc instanceof LoginPwUnencrypted loginPwUnencrypted) {
+ final var loginPassword = loginPwUnencrypted.getLoginPasswordUnencrypted();
+ return new LoginPwUnencryptedBuilder()
+ .setLoginPasswordUnencrypted(new LoginPasswordUnencryptedBuilder()
+ .setUsername(loginPassword.getUsername())
+ .setPassword(loginPassword.getPassword())
+ .build())
+ .build();
+ } else if (credentialsRpc instanceof KeyAuth keyAuth) {
+ final var loginPassword = keyAuth.getKeyBased();
+ return new KeyAuthBuilder()
+ .setKeyBased(new KeyBasedBuilder()
+ .setUsername(loginPassword.getUsername())
+ .setKeyId(loginPassword.getKeyId())
+ .build())
+ .build();
+ } else {
+ throw new IllegalArgumentException("Unsupported credential type: " + credentialsRpc.getClass());
}
-
- // nothing else needs to be encrypted
- return credentials;
}
- private void writeToConfigDS(final NetconfNode node, final NodeId nodeId,
+ private void writeToConfigDS(final Node node, final NodeId nodeId,
final SettableFuture<RpcResult<CreateDeviceOutput>> futureResult) {
final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
- final InstanceIdentifier<NetconfNode> niid = topologyPath.child(Node.class,
- new NodeKey(nodeId)).augmentation(NetconfNode.class);
+ final InstanceIdentifier<Node> niid = topologyPath.child(Node.class, new NodeKey(nodeId));
writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, niid, node);
writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {