*/
package org.opendaylight.netconf.sal.connect.util;
+import static java.util.Objects.requireNonNull;
+
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.List;
-import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
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.keystore.rev171017.AddTrustedCertificateOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddTrustedCertificateOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.Keystore;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.KeystoreBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.NetconfKeystoreService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveKeystoreEntryInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveKeystoreEntryOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredentialKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificate;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateKey;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class NetconfSalKeystoreService implements NetconfKeystoreService {
-
+@Singleton
+@Component(service = { })
+public final class NetconfSalKeystoreService implements NetconfKeystoreService, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(NetconfSalKeystoreService.class);
+ private static final InstanceIdentifier<Keystore> KEYSTORE_IID = InstanceIdentifier.create(Keystore.class);
+ // FIXME: we are populating config datastore, but there may be risks with concurrent access. We really should be
+ // using cluster singleton service here.
private final DataBroker dataBroker;
private final AAAEncryptionService encryptionService;
+ private final Registration reg;
- private final InstanceIdentifier<Keystore> keystoreIid = InstanceIdentifier.create(Keystore.class);
-
- public NetconfSalKeystoreService(final DataBroker dataBroker,
- final AAAEncryptionService encryptionService) {
- LOG.info("Starting NETCONF keystore service.");
+ @Inject
+ @Activate
+ public NetconfSalKeystoreService(@Reference final DataBroker dataBroker,
+ @Reference final AAAEncryptionService encryptionService, @Reference final RpcProviderService rpcProvider) {
+ this.dataBroker = requireNonNull(dataBroker);
+ this.encryptionService = requireNonNull(encryptionService);
- this.dataBroker = dataBroker;
- this.encryptionService = encryptionService;
-
- initKeystore();
+ reg = rpcProvider.registerRpcImplementation(NetconfKeystoreService.class, this);
+ LOG.info("NETCONF keystore service started");
}
- private void initKeystore() {
- final Keystore keystore = new KeystoreBuilder().build();
-
- final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
- writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, keystoreIid, keystore);
-
- try {
- writeTransaction.commit().get();
- LOG.debug("init keystore done");
- } catch (InterruptedException | ExecutionException exception) {
- LOG.error("Unable to initialize Netconf key-pair store.", exception);
- }
+ @PreDestroy
+ @Deactivate
+ @Override
+ public void close() {
+ reg.close();
+ LOG.info("NETCONF keystore service stopped");
}
@Override
for (final String id : input.getKeyId()) {
writeTransaction.delete(LogicalDatastoreType.CONFIGURATION,
- keystoreIid.child(KeyCredential.class, new KeyCredentialKey(id)));
+ KEYSTORE_IID.child(KeyCredential.class, new KeyCredentialKey(id)));
}
final SettableFuture<RpcResult<RemoveKeystoreEntryOutput>> rpcResult = SettableFuture.create();
for (KeyCredential keypair : keypairs) {
writeTransaction.merge(LogicalDatastoreType.CONFIGURATION,
- keystoreIid.child(KeyCredential.class, keypair.key()), keypair);
+ KEYSTORE_IID.child(KeyCredential.class, keypair.key()), keypair);
}
final SettableFuture<RpcResult<AddKeystoreEntryOutput>> rpcResult = SettableFuture.create();
for (TrustedCertificate certificate : input.nonnullTrustedCertificate().values()) {
writeTransaction.merge(LogicalDatastoreType.CONFIGURATION,
- keystoreIid.child(TrustedCertificate.class, certificate.key()), certificate);
+ KEYSTORE_IID.child(TrustedCertificate.class, certificate.key()), certificate);
}
final SettableFuture<RpcResult<AddTrustedCertificateOutput>> rpcResult = SettableFuture.create();
for (final String name : input.getName()) {
writeTransaction.delete(LogicalDatastoreType.CONFIGURATION,
- keystoreIid.child(TrustedCertificate.class, new TrustedCertificateKey(name)));
+ KEYSTORE_IID.child(TrustedCertificate.class, new TrustedCertificateKey(name)));
}
final SettableFuture<RpcResult<RemoveTrustedCertificateOutput>> rpcResult = SettableFuture.create();
for (PrivateKey key: input.nonnullPrivateKey().values()) {
writeTransaction.merge(LogicalDatastoreType.CONFIGURATION,
- keystoreIid.child(PrivateKey.class, key.key()), key);
+ KEYSTORE_IID.child(PrivateKey.class, key.key()), key);
}
final SettableFuture<RpcResult<AddPrivateKeyOutput>> rpcResult = SettableFuture.create();
for (final String name : input.getName()) {
writeTransaction.delete(LogicalDatastoreType.CONFIGURATION,
- keystoreIid.child(PrivateKey.class, new PrivateKeyKey(name)));
+ KEYSTORE_IID.child(PrivateKey.class, new PrivateKeyKey(name)));
}
final SettableFuture<RpcResult<RemovePrivateKeyOutput>> rpcResult = SettableFuture.create();
package org.opendaylight.netconf.sal.connect.netconf.util;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import org.mockito.junit.MockitoJUnitRunner;
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.LogicalDatastoreType;
import org.opendaylight.netconf.api.xml.XmlUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddPrivateKeyInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddTrustedCertificateInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddTrustedCertificateInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.NetconfKeystoreService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKeyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKeyKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificate;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateKey;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.w3c.dom.Document;
private DataBroker dataBroker;
@Mock
private AAAEncryptionService encryptionService;
+ @Mock
+ private RpcProviderService rpcProvider;
+ @Mock
+ private ObjectRegistration<?> rpcReg;
@Before
public void setUp() {
doReturn(writeTx).when(dataBroker).newWriteOnlyTransaction();
doNothing().when(writeTx)
.merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
+ doReturn(rpcReg).when(rpcProvider).registerRpcImplementation(eq(NetconfKeystoreService.class), any());
+ doNothing().when(rpcReg).close();
}
@Test
public void testAddPrivateKey() throws Exception {
doReturn(emptyFluentFuture()).when(writeTx).commit();
- NetconfSalKeystoreService keystoreService = new NetconfSalKeystoreService(dataBroker, encryptionService);
+ try (var keystoreService = new NetconfSalKeystoreService(dataBroker, encryptionService, rpcProvider)) {
+ final AddPrivateKeyInput input = getPrivateKeyInput();
+ keystoreService.addPrivateKey(input);
- final AddPrivateKeyInput input = getPrivateKeyInput();
- keystoreService.addPrivateKey(input);
-
- verify(writeTx, times(input.getPrivateKey().size() + 1))
- .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
+ verify(writeTx, times(input.nonnullPrivateKey().size()))
+ .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
+ }
}
@Test
public void testAddTrustedCertificate() throws Exception {
doReturn(emptyFluentFuture()).when(writeTx).commit();
- NetconfSalKeystoreService keystoreService = new NetconfSalKeystoreService(dataBroker, encryptionService);
-
- final AddTrustedCertificateInput input = getTrustedCertificateInput();
- keystoreService.addTrustedCertificate(input);
+ try (var keystoreService = new NetconfSalKeystoreService(dataBroker, encryptionService, rpcProvider)) {
+ final AddTrustedCertificateInput input = getTrustedCertificateInput();
+ keystoreService.addTrustedCertificate(input);
- verify(writeTx, times(input.getTrustedCertificate().size() + 1))
- .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
+ verify(writeTx, times(input.nonnullTrustedCertificate().size()))
+ .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
+ }
}
private AddPrivateKeyInput getPrivateKeyInput() throws Exception {