From: Tomas Olvecky Date: Thu, 10 Apr 2014 12:13:14 +0000 (+0200) Subject: Resolve Bug:707 - ConfigPusher should wait for netconf-impl to register JMX bean. X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~230^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=8f4996a3a1d486d83907c656a6c5390686c360a1 Resolve Bug:707 - ConfigPusher should wait for netconf-impl to register JMX bean. Fixes race condition that was observed in ITs, where config pusher started pushing empty configuration and immediately registered itself as notification listener of a JMX bean that was not yet present. Fix waits both for netconf-impl and config-netconf-connector services so that both dependencies are activated before pushing of configuration can occur. Change-Id: Id328dc3bd7e41bad59bb84b03461d89f5faeeea4 Signed-off-by: Tomas Olvecky --- diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index 8b6b1aefc1..054972dde7 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -52,7 +52,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; @@ -117,7 +117,7 @@ public class NetconfMappingTest extends AbstractConfigTest { @Mock NetconfOperationRouter netconfOperationRouter; @Mock - NetconfOperationServiceSnapshot netconfOperationServiceSnapshot; + NetconfOperationServiceSnapshotImpl netconfOperationServiceSnapshot; private TransactionProvider transactionProvider; diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java index 76afe8eb39..0cc55719e1 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java @@ -10,14 +10,17 @@ package org.opendaylight.controller.netconf.persist.impl.osgi; import com.google.common.annotations.VisibleForTesting; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler; import org.opendaylight.controller.netconf.persist.impl.ConfigPusher; import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator; +import org.opendaylight.controller.netconf.util.CloseableUtil; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.Filter; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; @@ -33,6 +36,7 @@ import java.util.concurrent.TimeUnit; public class ConfigPersisterActivator implements BundleActivator { private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterActivator.class); + private static final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY = "maxWaitForCapabilitiesMillis"; private static final long MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(2); @@ -43,9 +47,6 @@ public class ConfigPersisterActivator implements BundleActivator { public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass"; - - private static final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); - private List autoCloseables; @@ -55,56 +56,32 @@ public class ConfigPersisterActivator implements BundleActivator { autoCloseables = new ArrayList<>(); PropertiesProviderBaseImpl propertiesProvider = new PropertiesProviderBaseImpl(context); - final PersisterAggregator persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider); autoCloseables.add(persisterAggregator); - final long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider); - final List configs = persisterAggregator.loadLastConfigs(); - final long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider); + long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider); + List configs = persisterAggregator.loadLastConfigs(); + long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider); logger.trace("Following configs will be pushed: {}", configs); - ServiceTrackerCustomizer configNetconfCustomizer = new ServiceTrackerCustomizer() { - @Override - public NetconfOperationServiceFactory addingService(ServiceReference reference) { - NetconfOperationServiceFactory service = reference.getBundle().getBundleContext().getService(reference); - final ConfigPusher configPusher = new ConfigPusher(service, maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis); - logger.debug("Configuration Persister got %s", service); - final Thread pushingThread = new Thread(new Runnable() { - @Override - public void run() { - configPusher.pushConfigs(configs); - logger.info("Configuration Persister initialization completed."); - ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator); - synchronized (ConfigPersisterActivator.this) { - autoCloseables.add(jmxNotificationHandler); - } - } - }, "config-pusher"); - synchronized (ConfigPersisterActivator.this){ - autoCloseables.add(new AutoCloseable() { - @Override - public void close() throws Exception { - pushingThread.interrupt(); - } - }); - } - pushingThread.start(); - return service; - } - @Override - public void modifiedService(ServiceReference reference, NetconfOperationServiceFactory service) { - } + InnerCustomizer innerCustomizer = new InnerCustomizer(configs, maxWaitForCapabilitiesMillis, + conflictingVersionTimeoutMillis, persisterAggregator); + OuterCustomizer outerCustomizer = new OuterCustomizer(context, innerCustomizer); + new ServiceTracker<>(context, NetconfOperationProvider.class, outerCustomizer).open(); + } - @Override - public void removedService(ServiceReference reference, NetconfOperationServiceFactory service) { - } - }; + private long getConflictingVersionTimeoutMillis(PropertiesProviderBaseImpl propertiesProvider) { + String timeoutProperty = propertiesProvider.getProperty(CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY); + return timeoutProperty == null ? CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT : Long.valueOf(timeoutProperty); + } - Filter filter = context.createFilter(getFilterString()); + private long getMaxWaitForCapabilitiesMillis(PropertiesProviderBaseImpl propertiesProvider) { + String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY); + return timeoutProperty == null ? MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT : Long.valueOf(timeoutProperty); + } - ServiceTracker tracker = - new ServiceTracker<>(context, filter, configNetconfCustomizer); - tracker.open(); + @Override + public synchronized void stop(BundleContext context) throws Exception { + CloseableUtil.closeAll(autoCloseables); } @@ -116,32 +93,92 @@ public class ConfigPersisterActivator implements BundleActivator { ")"; } - private long getConflictingVersionTimeoutMillis(PropertiesProviderBaseImpl propertiesProvider) { - String timeoutProperty = propertiesProvider.getProperty(CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY); - return timeoutProperty == null ? CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT : Long.valueOf(timeoutProperty); - } + class OuterCustomizer implements ServiceTrackerCustomizer { + private final BundleContext context; + private final InnerCustomizer innerCustomizer; - private long getMaxWaitForCapabilitiesMillis(PropertiesProviderBaseImpl propertiesProvider) { - String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY); - return timeoutProperty == null ? MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT : Long.valueOf(timeoutProperty); - } + OuterCustomizer(BundleContext context, InnerCustomizer innerCustomizer) { + this.context = context; + this.innerCustomizer = innerCustomizer; + } - @Override - public synchronized void stop(BundleContext context) throws Exception { - Exception lastException = null; - for (AutoCloseable autoCloseable : autoCloseables) { + @Override + public NetconfOperationProvider addingService(ServiceReference reference) { + logger.trace("Got OuterCustomizer.addingService {}", reference); + // JMX was registered, track config-netconf-connector + Filter filter; try { - autoCloseable.close(); - } catch (Exception e) { - if (lastException == null) { - lastException = e; - } else { - lastException.addSuppressed(e); + filter = context.createFilter(getFilterString()); + } catch (InvalidSyntaxException e) { + throw new IllegalStateException(e); + } + new ServiceTracker<>(context, filter, innerCustomizer).open(); + return null; + } + + @Override + public void modifiedService(ServiceReference reference, NetconfOperationProvider service) { + + } + + @Override + public void removedService(ServiceReference reference, NetconfOperationProvider service) { + + } + } + + class InnerCustomizer implements ServiceTrackerCustomizer { + private final List configs; + private final PersisterAggregator persisterAggregator; + private final long maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis; + + + InnerCustomizer(List configs, long maxWaitForCapabilitiesMillis, long conflictingVersionTimeoutMillis, + PersisterAggregator persisterAggregator) { + this.configs = configs; + this.maxWaitForCapabilitiesMillis = maxWaitForCapabilitiesMillis; + this.conflictingVersionTimeoutMillis = conflictingVersionTimeoutMillis; + this.persisterAggregator = persisterAggregator; + } + + @Override + public NetconfOperationServiceFactory addingService(ServiceReference reference) { + logger.trace("Got InnerCustomizer.addingService {}", reference); + NetconfOperationServiceFactory service = reference.getBundle().getBundleContext().getService(reference); + + final ConfigPusher configPusher = new ConfigPusher(service, maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis); + logger.debug("Configuration Persister got {}", service); + final Thread pushingThread = new Thread(new Runnable() { + @Override + public void run() { + configPusher.pushConfigs(configs); + logger.info("Configuration Persister initialization completed."); + ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator); + synchronized (ConfigPersisterActivator.this) { + autoCloseables.add(jmxNotificationHandler); + } } + }, "config-pusher"); + synchronized (ConfigPersisterActivator.this) { + autoCloseables.add(new AutoCloseable() { + @Override + public void close() throws Exception { + pushingThread.interrupt(); + } + }); } + pushingThread.start(); + return service; + } + + @Override + public void modifiedService(ServiceReference reference, NetconfOperationServiceFactory service) { } - if (lastException != null) { - throw lastException; + + @Override + public void removedService(ServiceReference reference, NetconfOperationServiceFactory service) { } + } } + diff --git a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterTest.java b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterTest.java index 493ecd9250..b1bf232928 100644 --- a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterTest.java +++ b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterTest.java @@ -25,9 +25,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.xml.sax.SAXException; -import javax.management.MBeanServer; import java.io.IOException; -import java.lang.management.ManagementFactory; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; @@ -41,7 +39,6 @@ public class ConfigPersisterTest { private MockedBundleContext ctx; private ConfigPersisterActivator configPersisterActivator; - private static final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); private TestingExceptionHandler handler; diff --git a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/MockedBundleContext.java b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/MockedBundleContext.java index 8bc787bdef..95fd5f6549 100644 --- a/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/MockedBundleContext.java +++ b/opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/MockedBundleContext.java @@ -14,6 +14,7 @@ import org.mockito.MockitoAnnotations; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.config.persist.api.Persister; import org.opendaylight.controller.config.persist.api.PropertiesProvider; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.netconf.persist.impl.DummyAdapter; @@ -39,7 +40,7 @@ final class MockedBundleContext { @Mock private BundleContext context; @Mock - private Filter filter; + private Filter outerFilter, innerFilter; @Mock private ServiceReference serviceReference; @Mock @@ -53,12 +54,21 @@ final class MockedBundleContext { MockitoAnnotations.initMocks(this); doReturn(null).when(context).getProperty(anyString()); initContext(maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis); - doReturn(filter).when(context).createFilter(ConfigPersisterActivator.getFilterString()); - String filterString = "filter"; - doReturn(filterString).when(filter).toString(); - doNothing().when(context).addServiceListener(any(ServiceListener.class), eq(filterString)); + + String outerFilterString = "(objectClass=org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider)"; + doReturn(outerFilter).when(context).createFilter(outerFilterString); + doNothing().when(context).addServiceListener(any(ServiceListener.class), eq(outerFilterString)); ServiceReference[] toBeReturned = {serviceReference}; - doReturn(toBeReturned).when(context).getServiceReferences((String) null, filterString); + doReturn(toBeReturned).when(context).getServiceReferences(NetconfOperationProvider.class.getName(), null); + + String innerFilterString = "innerfilter"; + doReturn(innerFilterString).when(outerFilter).toString(); + + doReturn(innerFilter).when(context).createFilter(ConfigPersisterActivator.getFilterString()); + doReturn(innerFilterString).when(innerFilter).toString(); + doNothing().when(context).addServiceListener(any(ServiceListener.class), eq(innerFilterString)); + + doReturn(toBeReturned).when(context).getServiceReferences((String) null, innerFilterString); doReturn(bundle).when(serviceReference).getBundle(); doReturn(context).when(bundle).getBundleContext(); doReturn("").when(serviceReference).toString(); @@ -66,6 +76,7 @@ final class MockedBundleContext { doReturn(service).when(serviceFactory).createService(anyString()); doReturn(Collections.emptySet()).when(service).getCapabilities(); doNothing().when(service).close(); + doReturn("serviceFactoryMock").when(serviceFactory).toString(); } public BundleContext getBundleContext() { diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java index e2a2d832c7..dcd2ffad55 100644 --- a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java @@ -15,7 +15,5 @@ public interface NetconfOperationRouter extends AutoCloseable { Document onNetconfMessage(Document message, NetconfSession session) throws NetconfDocumentedException; - @Override - void close(); } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java index e0d7e319be..6a86ecd21f 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java @@ -12,9 +12,9 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java index f8d9a45c20..a44b7a799d 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java @@ -8,8 +8,8 @@ package org.opendaylight.controller.netconf.impl; -import static com.google.common.base.Preconditions.checkState; - +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfOperationRouter; @@ -25,8 +25,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; +import static com.google.common.base.Preconditions.checkState; public class NetconfServerSessionListener implements NetconfSessionListener { public static final String MESSAGE_ID = "message-id"; @@ -46,11 +45,15 @@ public class NetconfServerSessionListener implements NetconfSessionListener { - private final NetconfOperationServiceFactoryListener factoriesListener; + private final NetconfOperationProvider netconfOperationProvider; private final DefaultCommitNotificationProducer commitNotifier; @@ -26,10 +28,10 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto private final SessionMonitoringService monitor; - public NetconfServerSessionListenerFactory(NetconfOperationServiceFactoryListener factoriesListener, + public NetconfServerSessionListenerFactory(NetconfOperationProvider netconfOperationProvider, DefaultCommitNotificationProducer commitNotifier, SessionIdProvider idProvider, SessionMonitoringService monitor) { - this.factoriesListener = factoriesListener; + this.netconfOperationProvider = netconfOperationProvider; this.commitNotifier = commitNotifier; this.idProvider = idProvider; this.monitor = monitor; @@ -37,8 +39,8 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto @Override public NetconfServerSessionListener getSessionListener() { - NetconfOperationServiceSnapshot netconfOperationServiceSnapshot = factoriesListener.getSnapshot(idProvider - .getCurrentSessionId()); + NetconfOperationServiceSnapshot netconfOperationServiceSnapshot = netconfOperationProvider.getSnapshot( + getNetconfSessionIdForReporting(idProvider.getCurrentSessionId())); CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java index e052f61cc9..b3fa3467ad 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java @@ -14,7 +14,7 @@ import io.netty.util.Timer; import io.netty.util.concurrent.Promise; import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.util.NetconfUtil; import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage; import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil; @@ -31,6 +31,8 @@ import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import java.io.InputStream; +import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider.NetconfOperationProviderUtil.getNetconfSessionIdForReporting; + public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorFactory { public static final String SERVER_HELLO_XML_LOCATION = "/server_hello.xml"; @@ -39,13 +41,13 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF private static final Document helloMessageTemplate = loadHelloMessageTemplate(); private final SessionIdProvider idProvider; - private final NetconfOperationServiceFactoryListener factoriesListener; + private final NetconfOperationProvider netconfOperationProvider; private final long connectionTimeoutMillis; - public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationServiceFactoryListener factoriesListener, + public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider, SessionIdProvider idProvider, long connectionTimeoutMillis) { this.timer = timer; - this.factoriesListener = factoriesListener; + this.netconfOperationProvider = netconfOperationProvider; this.idProvider = idProvider; this.connectionTimeoutMillis = connectionTimeoutMillis; } @@ -86,7 +88,8 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF final Element capabilitiesElement = (Element) XmlUtil.evaluateXPath(capabilitiesXPath, helloMessageTemplate, XPathConstants.NODE); - CapabilityProvider capabilityProvider = new CapabilityProviderImpl(factoriesListener.getSnapshot(sessionId)); + CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationProvider.getSnapshot( + getNetconfSessionIdForReporting(sessionId))); for (String capability : capabilityProvider.getCapabilities()) { final Element capabilityElement = helloMessageTemplate.createElement(XmlNetconfConstants.CAPABILITY); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java index 8bc93e0512..af19335389 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java @@ -8,8 +8,6 @@ package org.opendaylight.controller.netconf.impl.mapping.operations; -import java.util.Collections; - import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -17,6 +15,8 @@ import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.w3c.dom.Document; import org.w3c.dom.Element; +import java.util.Collections; + public class DefaultCloseSession extends AbstractSingletonNetconfOperation { public static final String CLOSE_SESSION = "close-session"; private final AutoCloseable sessionResources; diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java index b8dc9550c7..04eda09287 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.netconf.impl.osgi; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; @@ -34,7 +35,6 @@ public class NetconfImplActivator implements BundleActivator { private NetconfOperationServiceFactoryTracker factoriesTracker; private DefaultCommitNotificationProducer commitNot; - private NetconfServerDispatcher dispatch; private NioEventLoopGroup eventLoopGroup; private HashedWheelTimer timer; private ServiceRegistration regMonitoring; @@ -64,11 +64,13 @@ public class NetconfImplActivator implements BundleActivator { NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer( serverNegotiatorFactory, listenerFactory); - dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup); + NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup); logger.info("Starting TCP netconf server at {}", address); dispatch.createServer(address); + context.registerService(NetconfOperationProvider.class, factoriesListener, null); + } private void startOperationServiceFactoryTracker(BundleContext context, NetconfOperationServiceFactoryListenerImpl factoriesListener) { diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java index 505c74714a..f9b0a128e0 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java @@ -16,7 +16,9 @@ import io.netty.util.internal.ConcurrentSet; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.mapping.api.Capability; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas; @@ -40,10 +42,10 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S private static final Logger logger = LoggerFactory.getLogger(NetconfMonitoringServiceImpl.class); private final Set sessions = new ConcurrentSet<>(); - private final NetconfOperationServiceFactoryListener factoriesListener; + private final NetconfOperationProvider netconfOperationProvider; - public NetconfMonitoringServiceImpl(NetconfOperationServiceFactoryListener factoriesListener) { - this.factoriesListener = factoriesListener; + public NetconfMonitoringServiceImpl(NetconfOperationProvider netconfOperationProvider) { + this.netconfOperationProvider = netconfOperationProvider; } @Override @@ -56,7 +58,7 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S @Override public void onSessionDown(NetconfManagementSession session) { logger.debug("Session {} down", session); - Preconditions.checkState(sessions.contains(session) == true, "Session %s not present", session); + Preconditions.checkState(sessions.contains(session), "Session %s not present", session); sessions.remove(session); } @@ -67,17 +69,23 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S @Override public Schemas getSchemas() { - // FIXME, session ID // capabilities should be split from operations (it will allow to move getSchema operation to monitoring module) - return transformSchemas(factoriesListener.getSnapshot(0)); + try (NetconfOperationServiceSnapshot snapshot = netconfOperationProvider.getSnapshot("netconf-monitoring")) { + return transformSchemas(snapshot.getServices()); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Exception while closing", e); + } } - private Schemas transformSchemas(NetconfOperationServiceSnapshot snapshot) { + private Schemas transformSchemas(Set services) { Set caps = Sets.newHashSet(); List schemas = Lists.newArrayList(); - for (NetconfOperationService netconfOperationService : snapshot.getServices()) { + + for (NetconfOperationService netconfOperationService : services) { // TODO check for duplicates ? move capability merging to snapshot // Split capabilities from operations first and delete this duplicate code caps.addAll(netconfOperationService.getCapabilities()); @@ -86,8 +94,9 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S for (Capability cap : caps) { SchemaBuilder builder = new SchemaBuilder(); - if(cap.getCapabilitySchema().isPresent() == false) + if (cap.getCapabilitySchema().isPresent() == false) { continue; + } Preconditions.checkState(cap.getModuleNamespace().isPresent()); builder.setNamespace(new Uri(cap.getModuleNamespace().get())); @@ -102,7 +111,7 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S builder.setFormat(Yang.class); - builder.setLocation(transformLocations(cap.getLocation().or(Collections. emptyList()))); + builder.setLocation(transformLocations(cap.getLocation().or(Collections.emptyList()))); builder.setKey(new SchemaKey(Yang.class, identifier, version)); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java index a358514453..80ba8388ef 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java @@ -25,6 +25,7 @@ import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -107,11 +108,11 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { String errorMessage = String.format("Unable to handle rpc %s on session %s", messageAsString, session); Map errorInfo = Maps.newHashMap(); - NetconfDocumentedException.ErrorTag tag = null; + NetconfDocumentedException.ErrorTag tag; if (e instanceof IllegalArgumentException) { errorInfo.put(NetconfDocumentedException.ErrorTag.operation_not_supported.toString(), e.getMessage()); tag = NetconfDocumentedException.ErrorTag.operation_not_supported; - } else if (e instanceof IllegalStateException) { + } else { errorInfo.put(NetconfDocumentedException.ErrorTag.operation_failed.toString(), e.getMessage()); tag = NetconfDocumentedException.ErrorTag.operation_failed; } @@ -130,7 +131,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { } @Override - public void close() { + public void close() throws Exception { netconfOperationServiceSnapshot.close(); } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java index 385ad09754..8e1052cfeb 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java @@ -16,5 +16,5 @@ public interface NetconfOperationServiceFactoryListener { void onRemoveNetconfOperationServiceFactory(NetconfOperationServiceFactory service); - NetconfOperationServiceSnapshot getSnapshot(long sessionId); + } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java index 134c38ba97..28bc2da778 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java @@ -7,12 +7,14 @@ */ package org.opendaylight.controller.netconf.impl.osgi; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; + import java.util.HashSet; import java.util.Set; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; - -public class NetconfOperationServiceFactoryListenerImpl implements NetconfOperationServiceFactoryListener { +public class NetconfOperationServiceFactoryListenerImpl implements NetconfOperationServiceFactoryListener, + NetconfOperationProvider { private final Set allFactories = new HashSet<>(); @Override @@ -26,8 +28,8 @@ public class NetconfOperationServiceFactoryListenerImpl implements NetconfOperat } @Override - public synchronized NetconfOperationServiceSnapshot getSnapshot(long sessionId) { - return new NetconfOperationServiceSnapshot(allFactories, sessionId); + public synchronized NetconfOperationServiceSnapshotImpl getSnapshot(String sessionIdForReporting) { + return new NetconfOperationServiceSnapshotImpl(allFactories, sessionIdForReporting); } } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshot.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java similarity index 51% rename from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshot.java rename to opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java index 5c08505091..ce312548b2 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshot.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java @@ -10,62 +10,46 @@ package org.opendaylight.controller.netconf.impl.osgi; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; +import org.opendaylight.controller.netconf.util.CloseableUtil; import java.util.Collections; import java.util.HashSet; import java.util.Set; -public class NetconfOperationServiceSnapshot implements AutoCloseable { - private static final Logger logger = LoggerFactory.getLogger(NetconfOperationServiceSnapshot.class); +public class NetconfOperationServiceSnapshotImpl implements NetconfOperationServiceSnapshot { private final Set services; private final String netconfSessionIdForReporting; - public NetconfOperationServiceSnapshot(Set factories, long sessionId) { + public NetconfOperationServiceSnapshotImpl(Set factories, String sessionIdForReporting) { Set services = new HashSet<>(); - netconfSessionIdForReporting = getNetconfSessionIdForReporting(sessionId); + netconfSessionIdForReporting = sessionIdForReporting; for (NetconfOperationServiceFactory factory : factories) { services.add(factory.createService(netconfSessionIdForReporting)); } this.services = Collections.unmodifiableSet(services); } - private static String getNetconfSessionIdForReporting(long sessionId) { - return "netconf session id " + sessionId; - } + + @Override public String getNetconfSessionIdForReporting() { return netconfSessionIdForReporting; } + @Override public Set getServices() { return services; } @Override - public void close() { - RuntimeException firstException = null; - for (NetconfOperationService service : services) { - try { - service.close(); - } catch (RuntimeException e) { - logger.warn("Got exception while closing {}", service, e); - if (firstException == null) { - firstException = e; - } else { - firstException.addSuppressed(e); - } - } - } - if (firstException != null) { - throw firstException; - } + public void close() throws Exception { + CloseableUtil.closeAll(services); } @Override public String toString() { - return "NetconfOperationServiceSnapshot{" + netconfSessionIdForReporting + '}'; + return "NetconfOperationServiceSnapshotImpl{" + netconfSessionIdForReporting + '}'; } } diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java index 9835c2393b..b60f4e3d82 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java @@ -15,7 +15,6 @@ import io.netty.util.HashedWheelTimer; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; import java.lang.management.ManagementFactory; @@ -34,7 +33,7 @@ public class NetconfDispatcherImplTest { commitNot = new DefaultCommitNotificationProducer( ManagementFactory.getPlatformMBeanServer()); - NetconfOperationServiceFactoryListener factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); + NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); SessionIdProvider idProvider = new SessionIdProvider(); hashedWheelTimer = new HashedWheelTimer(); diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java index 78933e4b0b..f61a28c2ab 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java @@ -32,9 +32,9 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl; import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; @@ -57,7 +57,7 @@ import java.util.Set; import static junit.framework.Assert.assertEquals; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -78,7 +78,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray( new ModuleFactory[0]))); - NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getFactoriesListener()); + NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider()); NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore())); @@ -178,15 +178,15 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { } - public NetconfOperationServiceFactoryListener getFactoriesListener() { - NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class); - NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class); + public NetconfOperationProvider getNetconfOperationProvider() { + NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class); + NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class); NetconfOperationService service = mock(NetconfOperationService.class); Set caps = Sets.newHashSet(); doReturn(caps).when(service).getCapabilities(); Set services = Sets.newHashSet(service); doReturn(services).when(snap).getServices(); - doReturn(snap).when(factoriesListener).getSnapshot(anyLong()); + doReturn(snap).when(factoriesListener).getSnapshot(anyString()); return factoriesListener; } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java index c4bcb3b227..a1892dbb0b 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java @@ -35,9 +35,9 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.ssh.NetconfSSHServer; import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider; @@ -71,7 +71,7 @@ import static java.util.Collections.emptyList; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; -import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -118,11 +118,11 @@ public class NetconfITTest extends AbstractNetconfConfigTest { } static NetconfMonitoringServiceImpl getNetconfMonitoringListenerService() { - NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class); - NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class); + NetconfOperationProvider netconfOperationProvider = mock(NetconfOperationProvider.class); + NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class); doReturn(Collections.emptySet()).when(snap).getServices(); - doReturn(snap).when(factoriesListener).getSnapshot(anyLong()); - return new NetconfMonitoringServiceImpl(factoriesListener); + doReturn(snap).when(netconfOperationProvider).getSnapshot(anyString()); + return new NetconfMonitoringServiceImpl(netconfOperationProvider); } @After diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java index 01b66ab0cf..5805e0afd1 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java @@ -7,54 +7,54 @@ */ package org.opendaylight.controller.netconf.it; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; import io.netty.channel.ChannelFuture; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Collection; -import java.util.List; -import java.util.Set; - import junit.framework.Assert; - import org.junit.Before; import org.junit.Test; import org.junit.matchers.JUnitMatchers; import org.mockito.Mock; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.spi.ModuleFactory; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl; import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator; import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; -import com.google.common.base.Charsets; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { @@ -75,7 +75,7 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray( new ModuleFactory[0]))); - monitoringService = new NetconfMonitoringServiceImpl(getFactoriesListener()); + monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider()); NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore())); @@ -171,16 +171,17 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { private void assertSessionElementsInResponse(Document document, int i) { int elementSize = document.getElementsByTagName("session-id").getLength(); - Assert.assertEquals(i, elementSize); + Assert.assertEquals("Incorrect number of session-id tags in " + XmlUtil.toString(document),i, elementSize); } private NetconfMessage loadGetMessage() throws Exception { return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml"); } - public static NetconfOperationServiceFactoryListener getFactoriesListener() { - NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class); - NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class); + public static NetconfOperationProvider getNetconfOperationProvider() throws Exception { + NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class); + NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class); + doNothing().when(snap).close(); NetconfOperationService service = mock(NetconfOperationService.class); Set caps = Sets.newHashSet(); caps.add(new Capability() { @@ -218,7 +219,7 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { doReturn(caps).when(service).getCapabilities(); Set services = Sets.newHashSet(service); doReturn(services).when(snap).getServices(); - doReturn(snap).when(factoriesListener).getSnapshot(anyLong()); + doReturn(snap).when(factoriesListener).getSnapshot(anyString()); return factoriesListener; } diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationProvider.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationProvider.java new file mode 100644 index 0000000000..c72c39c30c --- /dev/null +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationProvider.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. 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.controller.netconf.mapping.api; + +public interface NetconfOperationProvider { + + NetconfOperationServiceSnapshot getSnapshot(String sessionIdForReporting); + + public static class NetconfOperationProviderUtil { + + public static String getNetconfSessionIdForReporting(long sessionId) { + return "netconf session id " + sessionId; + } + + } + +} diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceSnapshot.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceSnapshot.java new file mode 100644 index 0000000000..eaa69379f7 --- /dev/null +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceSnapshot.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. 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.controller.netconf.mapping.api; + +import java.util.Set; + +public interface NetconfOperationServiceSnapshot extends AutoCloseable { + String getNetconfSessionIdForReporting(); + + Set getServices(); + +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/CloseableUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/CloseableUtil.java new file mode 100644 index 0000000000..27960dfe16 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/CloseableUtil.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. 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.controller.netconf.util; + +public class CloseableUtil { + + public static void closeAll(Iterable autoCloseables) throws Exception { + Exception lastException = null; + for (AutoCloseable autoCloseable : autoCloseables) { + try { + autoCloseable.close(); + } catch (Exception e) { + if (lastException == null) { + lastException = e; + } else { + lastException.addSuppressed(e); + } + } + } + if (lastException != null) { + throw lastException; + } + + } +}