*/
package org.opendaylight.bgpcep.programming.impl;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.MoreExecutors;
import io.netty.util.Timer;
import java.util.Collection;
+import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.programming.config.rev170301.odl.programming.OdlProgrammingConfigBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.programming.config.rev170301.odl.programming.OdlProgrammingConfigKey;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public final class InstructionDeployedImpl implements IntructionDeployer,
+public final class InstructionDeployerImpl implements IntructionDeployer,
ClusteredDataTreeChangeListener<OdlProgramming>, AutoCloseable {
- private static final Logger LOG = LoggerFactory.getLogger(InstructionDeployedImpl.class);
+ private static final Logger LOG = LoggerFactory.getLogger(InstructionDeployerImpl.class);
private final RpcProviderRegistry rpcProviderRegistry;
private final ListeningExecutorService exec = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
private final BundleContext bundleContext;
@GuardedBy("this")
private final Map<String, ProgrammingServiceImpl> programmingServices = new HashMap<>();
- private final ListenerRegistration<InstructionDeployedImpl> registration;
+ private final ListenerRegistration<InstructionDeployerImpl> registration;
private final InstanceIdentifier<OdlProgramming> iid;
private final ClusterSingletonServiceProvider cssp;
- public InstructionDeployedImpl(final DataBroker dataProvider, final RpcProviderRegistry rpcProviderRegistry,
+ public InstructionDeployerImpl(final DataBroker dataProvider, final RpcProviderRegistry rpcProviderRegistry,
final NotificationPublishService notifs, final Timer timer, final ClusterSingletonServiceProvider cssp,
final BundleContext bundleContext) {
this.dataProvider = Preconditions.checkNotNull(dataProvider);
this.iid = InstanceIdentifier.create(OdlProgramming.class);
final WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
- wTx.merge(LogicalDatastoreType.CONFIGURATION, this.iid, new OdlProgrammingBuilder().build());
+ wTx.merge(LogicalDatastoreType.CONFIGURATION, this.iid, new OdlProgrammingBuilder()
+ .setOdlProgrammingConfig(Collections.emptyList()).build());
Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
@Override
public void onSuccess(final Void result) {
- LOG.debug("Instruction Instance {} initialized successfully.", InstructionDeployedImpl.this.iid);
+ LOG.debug("Instruction Instance {} initialized successfully.", InstructionDeployerImpl.this.iid);
}
@Override
public void onFailure(final Throwable t) {
- LOG.error("Failed to initialize Instruction Instance {}.", InstructionDeployedImpl.this.iid, t);
+ LOG.error("Failed to initialize Instruction Instance {}.", InstructionDeployerImpl.this.iid, t);
}
});
new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, this.iid), this);
}
+ @VisibleForTesting
+ InstanceIdentifier<OdlProgramming> getInstructionIID(){
+ return this.iid;
+ }
+
+
private synchronized void createInstruction(final String instructionId) {
if (this.programmingServices.containsKey(instructionId)) {
LOG.warn("Instruction Scheduler {} already exist. New instance won't be created", instructionId);
@Override
public synchronized void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<OdlProgramming>> changes) {
final DataTreeModification<OdlProgramming> dataTreeModification = Iterables.getOnlyElement(changes);
- final DataObjectModification<OdlProgramming> rootNode = dataTreeModification.getRootNode();
- rootNode.getModifiedChildren()
- .forEach(dto->handleModification((DataObjectModification<OdlProgrammingConfig>) dto));
+ final Collection<DataObjectModification<? extends DataObject>> rootNode = dataTreeModification.getRootNode()
+ .getModifiedChildren();
+ if(rootNode.isEmpty()) {
+ return;
+ }
+ rootNode.forEach(dto->handleModification((DataObjectModification<OdlProgrammingConfig>) dto));
}
private void handleModification(final DataObjectModification<OdlProgrammingConfig> config) {
<reference id="clusterSingletonServiceProvider"
interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/>
- <bean id="IntructionDeployerImpl" class="org.opendaylight.bgpcep.programming.impl.InstructionDeployedImpl"
+ <bean id="IntructionDeployerImpl" class="org.opendaylight.bgpcep.programming.impl.InstructionDeployerImpl"
destroy-method="close">
<argument ref="dataBroker"/>
<argument ref="rpcRegistry"/>
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.bgpcep.programming.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentConfiguration;
+import static org.opendaylight.protocol.util.CheckUtil.checkPresentConfiguration;
+
+import io.netty.util.Timer;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.programming.config.rev170301.odl.programming.OdlProgrammingConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.programming.config.rev170301.odl.programming.OdlProgrammingConfigKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class InstructionDeployerImplTest extends AbstractDataBrokerTest {
+ @Mock
+ private RpcProviderRegistry rpcRegistry;
+ @Mock
+ private NotificationPublishService notifs;
+ @Mock
+ private Timer timer;
+ @Mock
+ private ClusterSingletonServiceProvider cssp;
+ @Mock
+ private ClusterSingletonServiceRegistration singletonServiceRegistration;
+ @Mock
+ private BundleContext bundleContext;
+ @Mock
+ private ServiceRegistration serviceRegistration;
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+ doAnswer(invocationOnMock -> this.singletonServiceRegistration).when(this.cssp)
+ .registerClusterSingletonService(any(ClusterSingletonService.class));
+
+ doReturn(this.serviceRegistration).when(this.bundleContext).registerService(any(String.class), any(), any());
+ }
+
+ @Test
+ public void testInstructionDeployer() throws Exception {
+ final InstructionDeployerImpl deployer = new InstructionDeployerImpl(getDataBroker(), this.rpcRegistry,
+ this.notifs, this.timer, this.cssp, this.bundleContext);
+
+ checkPresentConfiguration(getDataBroker(), deployer.getInstructionIID());
+
+ final String instructionId = "newInstruction";
+ deployer.writeConfiguration(instructionId);
+ final KeyedInstanceIdentifier<OdlProgrammingConfig, OdlProgrammingConfigKey> intructionIID =
+ deployer.getInstructionIID().child(OdlProgrammingConfig.class, new OdlProgrammingConfigKey(instructionId));
+ checkPresentConfiguration(getDataBroker(), intructionIID);
+ verify(this.cssp, timeout(100)).registerClusterSingletonService(any());
+ verify(this.bundleContext, timeout(100)).registerService(any(String.class), any(), any());
+
+ deployer.removeConfiguration(instructionId);
+ checkNotPresentConfiguration(getDataBroker(), intructionIID);
+ verify(this.singletonServiceRegistration, timeout(100)).close();
+ verify(this.serviceRegistration, timeout(100)).unregister();
+
+ deployer.close();
+ }
+}
\ No newline at end of file
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.MockitoAnnotations.initMocks;
import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
import static org.opendaylight.protocol.util.CheckUtil.checkPresentOperational;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
import org.opendaylight.bgpcep.programming.NanotimeUtil;
import org.opendaylight.bgpcep.programming.spi.Instruction;
import org.opendaylight.bgpcep.programming.spi.SchedulerException;
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
+ initMocks(this);
doAnswer(invocationOnMock -> {
this.singletonService = (ClusterSingletonService) invocationOnMock.getArguments()[0];
return this.singletonServiceRegistration;