From: Maros Marsalek Date: Fri, 13 Feb 2015 12:32:17 +0000 (+0100) Subject: BUG-2635 Prepare netconf monitoring service for md-sal monitoring. X-Git-Tag: release/lithium~515 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=4e59b3bd93bc8d7bf1880e98b75c87faab8f61c9;hp=-c BUG-2635 Prepare netconf monitoring service for md-sal monitoring. So that the monitoring service provides all the information in one place. Also move get-schema rpc into netconf-monitoring from netconf-impl. Change-Id: Ia7dc47ea4997df417795f079a7c045709dbaaf47 Signed-off-by: Maros Marsalek --- 4e59b3bd93bc8d7bf1880e98b75c87faab8f61c9 diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java index 82c04a50e0..590f4c4ceb 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java @@ -8,10 +8,19 @@ package org.opendaylight.controller.netconf.confignetconfconnector.osgi; +import com.google.common.base.Optional; import java.lang.management.ManagementFactory; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import javax.management.MBeanServer; import org.opendaylight.controller.config.util.ConfigRegistryJMXClient; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; +import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.yangtools.yang.model.api.Module; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,4 +77,117 @@ public class NetconfOperationServiceFactoryImpl implements NetconfOperationServi public NetconfOperationServiceImpl createService(String netconfSessionIdForReporting) { return new NetconfOperationServiceImpl(yangStoreService, jmxClient, netconfSessionIdForReporting); } + + + @Override + public Set getCapabilities() { + return setupCapabilities(yangStoreService); + } + + @Override + public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + return yangStoreService.registerCapabilityListener(listener); + } + + public static Set setupCapabilities(final YangStoreContext yangStoreSnapshot) { + Set capabilities = new HashSet<>(); + // [RFC6241] 8.3. Candidate Configuration Capability + capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0")); + + // TODO rollback on error not supported EditConfigXmlParser:100 + // [RFC6241] 8.5. Rollback-on-Error Capability + // capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:rollback-on-error:1.0")); + + Set modules = yangStoreSnapshot.getModules(); + for (Module module : modules) { + capabilities.add(new YangStoreCapability(module, yangStoreSnapshot.getModuleSource(module))); + } + + return capabilities; + } + + private static class BasicCapability implements Capability { + + private final String capability; + + private BasicCapability(final String capability) { + this.capability = capability; + } + + @Override + public String getCapabilityUri() { + return capability; + } + + @Override + public Optional getModuleNamespace() { + return Optional.absent(); + } + + @Override + public Optional getModuleName() { + return Optional.absent(); + } + + @Override + public Optional getRevision() { + return Optional.absent(); + } + + @Override + public Optional getCapabilitySchema() { + return Optional.absent(); + } + + @Override + public Collection getLocation() { + return Collections.emptyList(); + } + + @Override + public String toString() { + return capability; + } + } + + static final class YangStoreCapability extends BasicCapability { + + private final String content; + private final String revision; + private final String moduleName; + private final String moduleNamespace; + + public YangStoreCapability(final Module module, final String moduleContent) { + super(toCapabilityURI(module)); + this.content = moduleContent; + this.moduleName = module.getName(); + this.moduleNamespace = module.getNamespace().toString(); + this.revision = Util.writeDate(module.getRevision()); + } + + @Override + public Optional getCapabilitySchema() { + return Optional.of(content); + } + + private static String toCapabilityURI(final Module module) { + return String.valueOf(module.getNamespace()) + "?module=" + + module.getName() + "&revision=" + Util.writeDate(module.getRevision()); + } + + @Override + public Optional getModuleName() { + return Optional.of(moduleName); + } + + @Override + public Optional getModuleNamespace() { + return Optional.of(moduleNamespace); + } + + @Override + public Optional getRevision() { + return Optional.of(revision); + } + } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java index ef0a72c0f0..28001851cc 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java @@ -8,18 +8,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector.osgi; -import com.google.common.base.Optional; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.Set; import org.opendaylight.controller.config.util.ConfigRegistryJMXClient; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; -import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; -import org.opendaylight.yangtools.yang.model.api.Module; /** * Manages life cycle of {@link YangStoreContext}. @@ -28,132 +21,23 @@ public class NetconfOperationServiceImpl implements NetconfOperationService { private final NetconfOperationProvider operationProvider; private final TransactionProvider transactionProvider; - private final YangStoreService yangStoreService; public NetconfOperationServiceImpl(final YangStoreService yangStoreService, final ConfigRegistryJMXClient jmxClient, final String netconfSessionIdForReporting) { - this.yangStoreService = yangStoreService; - transactionProvider = new TransactionProvider(jmxClient, netconfSessionIdForReporting); operationProvider = new NetconfOperationProvider(yangStoreService, jmxClient, transactionProvider, netconfSessionIdForReporting); } - @Override - public void close() { - transactionProvider.close(); - } - - @Override - public Set getCapabilities() { - return setupCapabilities(yangStoreService); - } - @Override public Set getNetconfOperations() { return operationProvider.getOperations(); } - private static Set setupCapabilities(final YangStoreContext yangStoreSnapshot) { - Set capabilities = new HashSet<>(); - // [RFC6241] 8.3. Candidate Configuration Capability - capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0")); - - // TODO rollback on error not supported EditConfigXmlParser:100 - // [RFC6241] 8.5. Rollback-on-Error Capability - // capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:rollback-on-error:1.0")); - - Set modules = yangStoreSnapshot.getModules(); - for (Module module : modules) { - capabilities.add(new YangStoreCapability(module, yangStoreSnapshot.getModuleSource(module))); - } - - return capabilities; - } - - private static class BasicCapability implements Capability { - - private final String capability; - - private BasicCapability(final String capability) { - this.capability = capability; - } - - @Override - public String getCapabilityUri() { - return capability; - } - - @Override - public Optional getModuleNamespace() { - return Optional.absent(); - } - - @Override - public Optional getModuleName() { - return Optional.absent(); - } - - @Override - public Optional getRevision() { - return Optional.absent(); - } - - @Override - public Optional getCapabilitySchema() { - return Optional.absent(); - } - - @Override - public Collection getLocation() { - return Collections.emptyList(); - } - - @Override - public String toString() { - return capability; - } + @Override + public void close() { + transactionProvider.close(); } - private static final class YangStoreCapability extends BasicCapability { - - private final String content; - private final String revision; - private final String moduleName; - private final String moduleNamespace; - - public YangStoreCapability(final Module module, final String moduleContent) { - super(toCapabilityURI(module)); - this.content = moduleContent; - this.moduleName = module.getName(); - this.moduleNamespace = module.getNamespace().toString(); - this.revision = Util.writeDate(module.getRevision()); - } - - @Override - public Optional getCapabilitySchema() { - return Optional.of(content); - } - - private static String toCapabilityURI(final Module module) { - return String.valueOf(module.getNamespace()) + "?module=" - + module.getName() + "&revision=" + Util.writeDate(module.getRevision()); - } - - @Override - public Optional getModuleName() { - return Optional.of(moduleName); - } - - @Override - public Optional getModuleNamespace() { - return Optional.of(moduleNamespace); - } - - @Override - public Optional getRevision() { - return Optional.of(revision); - } - } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java index de151a8969..60b8b8f468 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java @@ -14,6 +14,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import java.lang.ref.SoftReference; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -21,6 +22,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicReference; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; import org.opendaylight.controller.netconf.notifications.BaseNetconfNotificationListener; import org.opendaylight.controller.netconf.notifications.BaseNotificationPublisherRegistration; import org.opendaylight.controller.netconf.notifications.NetconfNotificationCollector; @@ -77,6 +80,8 @@ public class YangStoreService implements YangStoreContext { } }); + private final Set listeners = Collections.synchronizedSet(new HashSet()); + public YangStoreService(final SchemaContextProvider schemaContextProvider, final BundleContext context) { this(schemaContextProvider, new NotificationCollectorTracker(context)); } @@ -130,7 +135,31 @@ public class YangStoreService implements YangStoreContext { notificationExecutor.submit(new CapabilityChangeNotifier(previous)); } + public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + if(ref.get() == null || ref.get().get() == null) { + getYangStoreSnapshot(); + } + + this.listeners.add(listener); + listener.onCapabilitiesAdded(NetconfOperationServiceFactoryImpl.setupCapabilities(ref.get().get())); + + return new AutoCloseable() { + @Override + public void close() throws Exception { + YangStoreService.this.listeners.remove(listener); + } + }; + } + + private static final Function MODULE_TO_CAPABILITY = new Function() { + @Override + public Capability apply(final Module module) { + return new NetconfOperationServiceFactoryImpl.YangStoreCapability(module, module.getSource()); + } + }; + private final class CapabilityChangeNotifier implements Runnable { + private final YangStoreSnapshot previous; public CapabilityChangeNotifier(final YangStoreSnapshot previous) { @@ -142,7 +171,19 @@ public class YangStoreService implements YangStoreContext { final YangStoreContext current = getYangStoreSnapshot(); if(current.equals(previous) == false) { - notificationPublisher.onCapabilityChanged(computeDiff(previous, current)); + final Sets.SetView removed = Sets.difference(previous.getModules(), current.getModules()); + final Sets.SetView added = Sets.difference(current.getModules(), previous.getModules()); + + // Notify notification manager + notificationPublisher.onCapabilityChanged(computeDiff(removed, added)); + + // Notify direct capability listener TODO would it not be better if the capability listeners went through notification manager ? + for (final CapabilityListener listener : listeners) { + listener.onCapabilitiesAdded(Sets.newHashSet(Collections2.transform(added, MODULE_TO_CAPABILITY))); + } + for (final CapabilityListener listener : listeners) { + listener.onCapabilitiesRemoved(Sets.newHashSet(Collections2.transform(removed, MODULE_TO_CAPABILITY))); + } } } } @@ -155,10 +196,7 @@ public class YangStoreService implements YangStoreContext { } }; - static NetconfCapabilityChange computeDiff(final YangStoreContext previous, final YangStoreContext current) { - final Sets.SetView removed = Sets.difference(previous.getModules(), current.getModules()); - final Sets.SetView added = Sets.difference(current.getModules(), previous.getModules()); - + static NetconfCapabilityChange computeDiff(final Sets.SetView removed, final Sets.SetView added) { final NetconfCapabilityChangeBuilder netconfCapabilityChangeBuilder = new NetconfCapabilityChangeBuilder(); netconfCapabilityChangeBuilder.setChangedBy(new ChangedByBuilder().setServerOrUser(new ServerBuilder().setServer(true).build()).build()); netconfCapabilityChangeBuilder.setDeletedCapability(Lists.newArrayList(Collections2.transform(removed, MODULE_TO_URI))); 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 f1fc27725b..b1222997fb 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 @@ -95,8 +95,8 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; -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; @@ -141,7 +141,9 @@ public class NetconfMappingTest extends AbstractConfigTest { @Mock NetconfOperationRouter netconfOperationRouter; @Mock - NetconfOperationServiceSnapshotImpl netconfOperationServiceSnapshot; + AggregatedNetconfOperationServiceFactory netconfOperationServiceSnapshot; + @Mock + private AutoCloseable sessionCloseable; private TransactionProvider transactionProvider; @@ -157,13 +159,12 @@ public class NetconfMappingTest extends AbstractConfigTest { doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap(); doReturn(getModules()).when(this.yangStoreSnapshot).getModules(); - doNothing().when(netconfOperationServiceSnapshot).close(); this.factory = new NetconfTestImplModuleFactory(); this.factory2 = new DepTestImplModuleFactory(); this.factory3 = new IdentityTestModuleFactory(); factory4 = new TestImplModuleFactory(); - + doNothing().when(sessionCloseable).close(); super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, this.factory, this.factory2, this.factory3, factory4)); @@ -376,7 +377,7 @@ public class NetconfMappingTest extends AbstractConfigTest { edit("netconfMessages/editConfig_none.xml"); closeSession(); - verify(netconfOperationServiceSnapshot).close(); + verify(sessionCloseable).close(); verifyNoMoreInteractions(netconfOperationRouter); verifyNoMoreInteractions(netconfOperationServiceSnapshot); } @@ -390,7 +391,7 @@ public class NetconfMappingTest extends AbstractConfigTest { private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException { - DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID, netconfOperationServiceSnapshot); + DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID, sessionCloseable); executeOp(closeOp, "netconfMessages/closeSession.xml"); } diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java index 0aebc68bbe..22b061a128 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java @@ -33,10 +33,10 @@ import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.persist.api.ConfigPusher; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.config.persist.api.Persister; +import org.opendaylight.controller.netconf.api.Capability; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; @@ -177,20 +177,20 @@ public class ConfigPusherImpl implements ConfigPusher { } catch(RuntimeException e) { throw new NotEnoughCapabilitiesException("Netconf service not stable for " + idForReporting, e); } - Set notFoundDiff = computeNotFoundCapabilities(expectedCapabilities, serviceCandidate); + Set notFoundDiff = computeNotFoundCapabilities(expectedCapabilities, configNetconfConnector); if (notFoundDiff.isEmpty()) { return serviceCandidate; } else { serviceCandidate.close(); LOG.trace("Netconf server did not provide required capabilities for {} ", idForReporting, "Expected but not found: {}, all expected {}, current {}", - notFoundDiff, expectedCapabilities, serviceCandidate.getCapabilities() + notFoundDiff, expectedCapabilities, configNetconfConnector.getCapabilities() ); throw new NotEnoughCapabilitiesException("Not enough capabilities for " + idForReporting + ". Expected but not found: " + notFoundDiff); } } - private static Set computeNotFoundCapabilities(Set expectedCapabilities, NetconfOperationService serviceCandidate) { + private static Set computeNotFoundCapabilities(Set expectedCapabilities, NetconfOperationServiceFactory serviceCandidate) { Collection actual = Collections2.transform(serviceCandidate.getCapabilities(), new Function() { @Override public String apply(@Nonnull final Capability input) { 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 6188492228..b27bec3c83 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 @@ -17,7 +17,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.management.MBeanServer; import org.opendaylight.controller.config.persist.api.ConfigPusher; 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.ConfigPusherImpl; import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator; @@ -71,7 +70,7 @@ public class ConfigPersisterActivator implements BundleActivator { InnerCustomizer innerCustomizer = new InnerCustomizer(configs, maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis, persisterAggregator); OuterCustomizer outerCustomizer = new OuterCustomizer(context, innerCustomizer); - new ServiceTracker<>(context, NetconfOperationProvider.class, outerCustomizer).open(); + new ServiceTracker<>(context, NetconfOperationServiceFactory.class, outerCustomizer).open(); } private long getConflictingVersionTimeoutMillis(PropertiesProviderBaseImpl propertiesProvider) { @@ -104,7 +103,7 @@ public class ConfigPersisterActivator implements BundleActivator { ")"; } - class OuterCustomizer implements ServiceTrackerCustomizer { + class OuterCustomizer implements ServiceTrackerCustomizer { private final BundleContext context; private final InnerCustomizer innerCustomizer; @@ -114,7 +113,7 @@ public class ConfigPersisterActivator implements BundleActivator { } @Override - public NetconfOperationProvider addingService(ServiceReference reference) { + public NetconfOperationServiceFactory addingService(ServiceReference reference) { LOG.trace("Got OuterCustomizer.addingService {}", reference); // JMX was registered, track config-netconf-connector Filter filter; @@ -128,12 +127,12 @@ public class ConfigPersisterActivator implements BundleActivator { } @Override - public void modifiedService(ServiceReference reference, NetconfOperationProvider service) { + public void modifiedService(ServiceReference reference, NetconfOperationServiceFactory service) { } @Override - public void removedService(ServiceReference reference, NetconfOperationProvider service) { + 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 142d8f5226..7b79e41f38 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 @@ -20,8 +20,8 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.ConflictingVersionException; +import org.opendaylight.controller.netconf.api.Capability; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; @@ -41,9 +41,10 @@ public class ConfigPersisterTest { private TestingExceptionHandler handler; - private void setUpContextAndStartPersister(String requiredCapability) throws Exception { + private void setUpContextAndStartPersister(String requiredCapability, final NetconfOperationService conflictingService) throws Exception { DummyAdapterWithInitialSnapshot.expectedCapability = requiredCapability; ctx = new MockedBundleContext(1000, 1000); + doReturn(getConflictingService()).when(ctx.serviceFactory).createService(anyString()); configPersisterActivator = new ConfigPersisterActivator(); configPersisterActivator.start(ctx.getBundleContext()); } @@ -62,7 +63,7 @@ public class ConfigPersisterTest { @Test public void testPersisterNotAllCapabilitiesProvided() throws Exception { - setUpContextAndStartPersister("required-cap"); + setUpContextAndStartPersister("required-cap", getConflictingService()); Thread.sleep(2000); handler.assertException(IllegalStateException.class, "Max wait for capabilities reached.Not enough capabilities " + "for . Expected but not found: [required-cap]"); @@ -71,7 +72,7 @@ public class ConfigPersisterTest { @Test public void testPersisterSuccessfulPush() throws Exception { - setUpContextAndStartPersister("cap1"); + setUpContextAndStartPersister("cap1", getConflictingService()); NetconfOperationService service = getWorkingService(getOKDocument()); doReturn(service).when(ctx.serviceFactory).createService(anyString()); Thread.sleep(2000); @@ -86,7 +87,7 @@ public class ConfigPersisterTest { public NetconfOperationService getWorkingService(Document document) throws SAXException, IOException, NetconfDocumentedException { NetconfOperationService service = mock(NetconfOperationService.class); Capability capability = mock(Capability.class); - doReturn(Sets.newHashSet(capability)).when(service).getCapabilities(); +// doReturn(Sets.newHashSet(capability)).when(service).getCapabilities(); doReturn("cap1").when(capability).getCapabilityUri(); @@ -109,9 +110,8 @@ public class ConfigPersisterTest { @Test public void testPersisterConflictingVersionException() throws Exception { - setUpContextAndStartPersister("cap1"); + setUpContextAndStartPersister("cap1", getConflictingService()); - doReturn(getConflictingService()).when(ctx.serviceFactory).createService(anyString()); Thread.sleep(2000); handler.assertException(IllegalStateException.class, "Max wait for conflicting version stabilization timeout"); } @@ -131,7 +131,7 @@ public class ConfigPersisterTest { @Test public void testSuccessConflictingVersionException() throws Exception { - setUpContextAndStartPersister("cap1"); + setUpContextAndStartPersister("cap1", getConflictingService()); doReturn(getConflictingService()).when(ctx.serviceFactory).createService(anyString()); Thread.sleep(500); // working service: 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 0d866ecda7..bd18c8c30e 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 @@ -12,6 +12,7 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -28,7 +29,7 @@ import org.opendaylight.controller.config.persist.api.ConfigPusher; 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.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.netconf.persist.impl.DummyAdapter; @@ -60,11 +61,11 @@ final class MockedBundleContext { doReturn(null).when(context).getProperty(anyString()); initContext(maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis); - String outerFilterString = "(objectClass=org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider)"; + String outerFilterString = "(objectClass=org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory)"; doReturn(outerFilter).when(context).createFilter(outerFilterString); doNothing().when(context).addServiceListener(any(ServiceListener.class), eq(outerFilterString)); ServiceReference[] toBeReturned = {serviceReference}; - doReturn(toBeReturned).when(context).getServiceReferences(NetconfOperationProvider.class.getName(), null); + doReturn(toBeReturned).when(context).getServiceReferences(NetconfOperationServiceFactory.class.getName(), null); String innerFilterString = "innerfilter"; doReturn(innerFilterString).when(outerFilter).toString(); @@ -77,9 +78,12 @@ final class MockedBundleContext { doReturn(bundle).when(serviceReference).getBundle(); doReturn(context).when(bundle).getBundleContext(); doReturn("").when(serviceReference).toString(); + doReturn("context").when(context).toString(); doReturn(serviceFactory).when(context).getService(any(ServiceReference.class)); doReturn(service).when(serviceFactory).createService(anyString()); - doReturn(Collections.emptySet()).when(service).getCapabilities(); + final Capability cap = mock(Capability.class); + doReturn("cap1").when(cap).getCapabilityUri(); + doReturn(Collections.singleton(cap)).when(serviceFactory).getCapabilities(); doNothing().when(service).close(); doReturn("serviceFactoryMock").when(serviceFactory).toString(); diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java index f54c5e9838..cc22dd51aa 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java @@ -8,34 +8,17 @@ package org.opendaylight.controller.netconf.mdsal.connector; -import com.google.common.base.Optional; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.Set; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; -import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class MdsalNetconfOperationService implements NetconfOperationService { - private static final Logger LOG = LoggerFactory.getLogger(MdsalNetconfOperationService.class); - - private final CurrentSchemaContext schemaContext; - private final String netconfSessionIdForReporting; private final OperationProvider operationProvider; public MdsalNetconfOperationService(final CurrentSchemaContext schemaContext, final String netconfSessionIdForReporting, final DOMDataBroker dataBroker) { - this.schemaContext = schemaContext; - // TODO schema contexts are different in data broker and the one we receive here ... the one received here should be updated same way as broker is - this.netconfSessionIdForReporting = netconfSessionIdForReporting; this.operationProvider = new OperationProvider(netconfSessionIdForReporting, schemaContext, dataBroker); } @@ -44,115 +27,9 @@ public class MdsalNetconfOperationService implements NetconfOperationService { } - // TODO does this get called dynamically ? - @Override - public Set getCapabilities() { - final Set capabilities = new HashSet<>(); - // [RFC6241] 8.3. Candidate Configuration Capability - capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0")); - - final SchemaContext currentContext = schemaContext.getCurrentContext(); - final Set modules = currentContext.getModules(); - for (final Module module : modules) { - if(currentContext.getModuleSource(module).isPresent()) { - capabilities.add(new YangStoreCapability(module, currentContext.getModuleSource(module).get())); - } else { - LOG.warn("Missing source for module {}. This module will not be available from netconf server for session {}", - module, netconfSessionIdForReporting); - } - } - - return capabilities; - } - @Override public Set getNetconfOperations() { return operationProvider.getOperations(); } - // TODO reuse from netconf impl - private static class BasicCapability implements Capability { - - private final String capability; - - private BasicCapability(final String capability) { - this.capability = capability; - } - - @Override - public String getCapabilityUri() { - return capability; - } - - @Override - public Optional getModuleNamespace() { - return Optional.absent(); - } - - @Override - public Optional getModuleName() { - return Optional.absent(); - } - - @Override - public Optional getRevision() { - return Optional.absent(); - } - - @Override - public Optional getCapabilitySchema() { - return Optional.absent(); - } - - @Override - public Collection getLocation() { - return Collections.emptyList(); - } - - @Override - public String toString() { - return capability; - } - } - - private static final class YangStoreCapability extends BasicCapability { - - private final String content; - private final String revision; - private final String moduleName; - private final String moduleNamespace; - - public YangStoreCapability(final Module module, final String moduleContent) { - super(toCapabilityURI(module)); - this.content = moduleContent; - this.moduleName = module.getName(); - this.moduleNamespace = module.getNamespace().toString(); - this.revision = SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()); - } - - @Override - public Optional getCapabilitySchema() { - return Optional.of(content); - } - - private static String toCapabilityURI(final Module module) { - return String.valueOf(module.getNamespace()) + "?module=" - + module.getName() + "&revision=" + SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()); - } - - @Override - public Optional getModuleName() { - return Optional.of(moduleName); - } - - @Override - public Optional getModuleNamespace() { - return Optional.of(moduleNamespace); - } - - @Override - public Optional getRevision() { - return Optional.of(revision); - } - } } diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java index 098f25bf4a..9bd71c3c7c 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java @@ -8,13 +8,27 @@ package org.opendaylight.controller.netconf.mdsal.connector; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class MdsalNetconfOperationServiceFactory implements NetconfOperationServiceFactory, AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(MdsalNetconfOperationServiceFactory.class); + private final DOMDataBroker dataBroker; private final CurrentSchemaContext currentSchemaContext; @@ -32,4 +46,120 @@ public class MdsalNetconfOperationServiceFactory implements NetconfOperationServ public void close() throws Exception { currentSchemaContext.close(); } + + @Override + public Set getCapabilities() { + final Set capabilities = new HashSet<>(); + // [RFC6241] 8.3. Candidate Configuration Capability + capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0")); + + final SchemaContext currentContext = currentSchemaContext.getCurrentContext(); + final Set modules = currentContext.getModules(); + for (final Module module : modules) { + if(currentContext.getModuleSource(module).isPresent()) { + capabilities.add(new YangStoreCapability(module, currentContext.getModuleSource(module).get())); + } else { + LOG.warn("Missing source for module {}. This module will not be available from netconf server", + module); + } + } + + return capabilities; + } + + @Override + public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + // TODO provide notifications about changed schemas + return new AutoCloseable() { + @Override + public void close() throws Exception { + + } + }; + } + + private static class BasicCapability implements Capability { + + private final String capability; + + private BasicCapability(final String capability) { + this.capability = capability; + } + + @Override + public String getCapabilityUri() { + return capability; + } + + @Override + public Optional getModuleNamespace() { + return Optional.absent(); + } + + @Override + public Optional getModuleName() { + return Optional.absent(); + } + + @Override + public Optional getRevision() { + return Optional.absent(); + } + + @Override + public Optional getCapabilitySchema() { + return Optional.absent(); + } + + @Override + public Collection getLocation() { + return Collections.emptyList(); + } + + @Override + public String toString() { + return capability; + } + } + + private static final class YangStoreCapability extends BasicCapability { + + private final String content; + private final String revision; + private final String moduleName; + private final String moduleNamespace; + + public YangStoreCapability(final Module module, final String moduleContent) { + super(toCapabilityURI(module)); + this.content = moduleContent; + this.moduleName = module.getName(); + this.moduleNamespace = module.getNamespace().toString(); + this.revision = SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()); + } + + @Override + public Optional getCapabilitySchema() { + return Optional.of(content); + } + + private static String toCapabilityURI(final Module module) { + return String.valueOf(module.getNamespace()) + "?module=" + + module.getName() + "&revision=" + SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()); + } + + @Override + public Optional getModuleName() { + return Optional.of(moduleName); + } + + @Override + public Optional getModuleNamespace() { + return Optional.of(moduleNamespace); + } + + @Override + public Optional getRevision() { + return Optional.of(revision); + } + } } diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/Capability.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/Capability.java similarity index 93% rename from opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/Capability.java rename to opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/Capability.java index 408756bf4d..6a061b1ea9 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/Capability.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/Capability.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.mapping.api; +package org.opendaylight.controller.netconf.api; import com.google.common.base.Optional; import java.util.Collection; diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/CapabilityListener.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/CapabilityListener.java new file mode 100644 index 0000000000..5d9468c8ea --- /dev/null +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/CapabilityListener.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015 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.api.monitoring; + +import java.util.Set; +import org.opendaylight.controller.netconf.api.Capability; + +public interface CapabilityListener { + + void onCapabilitiesAdded(Set addedCaps); + + void onCapabilitiesRemoved(Set removedCaps); +} diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/NetconfMonitoringService.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/NetconfMonitoringService.java index 51eea9307d..3f0e1a1aa5 100644 --- a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/NetconfMonitoringService.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/NetconfMonitoringService.java @@ -7,12 +7,19 @@ */ package org.opendaylight.controller.netconf.api.monitoring; +import com.google.common.base.Optional; +import java.util.Set; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions; -public interface NetconfMonitoringService { +public interface NetconfMonitoringService extends CapabilityListener, SessionListener { Sessions getSessions(); Schemas getSchemas(); + + String getSchemaForCapability(String moduleName, Optional revision); + + Set getCapabilities(); + } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/SessionMonitoringService.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/SessionListener.java similarity index 59% rename from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/SessionMonitoringService.java rename to opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/SessionListener.java index 7a0b8b7170..a11fb879ca 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/SessionMonitoringService.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/SessionListener.java @@ -1,16 +1,17 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2015 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.impl.osgi; -import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; - -public interface SessionMonitoringService { +package org.opendaylight.controller.netconf.api.monitoring; +/** + * Created by mmarsale on 13.2.2015. + */ +public interface SessionListener { void onSessionUp(NetconfManagementSession session); void onSessionDown(NetconfManagementSession session); diff --git a/opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang b/opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang index f775da91c0..e2b0d35867 100644 --- a/opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang +++ b/opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang @@ -19,4 +19,9 @@ module netconf-northbound { config:java-class "org.opendaylight.controller.netconf.api.NetconfServerDispatcher"; } + identity netconf-server-monitoring { + base "config:service-type"; + config:java-class "org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService"; + } + } \ No newline at end of file diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java index e64620d4ad..c1570f4311 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java @@ -1,13 +1,13 @@ package org.opendaylight.controller.config.yang.config.netconf.northbound.impl; import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.impl.CommitNotifier; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; public class NetconfServerDispatcherModule extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfServerDispatcherModule { @@ -27,8 +27,8 @@ public class NetconfServerDispatcherModule extends org.opendaylight.controller.c @Override public java.lang.AutoCloseable createInstance() { - final NetconfOperationServiceFactoryListenerImpl aggregatedOpProvider = getAggregatedOpProvider(); - final SessionMonitoringService monitoringService = startMonitoringService(aggregatedOpProvider); + final AggregatedNetconfOperationServiceFactory aggregatedOpProvider = getAggregatedOpProvider(); + final NetconfMonitoringService monitoringService = startMonitoringService(aggregatedOpProvider); final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( getTimerDependency(), aggregatedOpProvider, new SessionIdProvider(), getConnectionTimeoutMillis(), CommitNotifier.NoopCommitNotifier.getInstance(), monitoringService); final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( @@ -44,12 +44,12 @@ public class NetconfServerDispatcherModule extends org.opendaylight.controller.c } - private NetconfMonitoringServiceImpl startMonitoringService(final NetconfOperationServiceFactoryListenerImpl netconfOperationProvider) { + private NetconfMonitoringServiceImpl startMonitoringService(final AggregatedNetconfOperationServiceFactory netconfOperationProvider) { return new NetconfMonitoringServiceImpl(netconfOperationProvider); } - private NetconfOperationServiceFactoryListenerImpl getAggregatedOpProvider() { - final NetconfOperationServiceFactoryListenerImpl netconfOperationProvider = new NetconfOperationServiceFactoryListenerImpl(); + private AggregatedNetconfOperationServiceFactory getAggregatedOpProvider() { + final AggregatedNetconfOperationServiceFactory netconfOperationProvider = new AggregatedNetconfOperationServiceFactory(); for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getMappersDependency()) { netconfOperationProvider.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory); } 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 deleted file mode 100644 index 13cc973ba7..0000000000 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.impl; - -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; -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; - -public class CapabilityProviderImpl implements CapabilityProvider { - private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot; - private final Set capabilityURIs; - - private static final Logger LOG = LoggerFactory.getLogger(CapabilityProviderImpl.class); - - public CapabilityProviderImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) { - this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot; - Map urisToCapabilitiesInternalMap = getCapabilitiesInternal(netconfOperationServiceSnapshot); - List capabilityURIs = new ArrayList<>(urisToCapabilitiesInternalMap.keySet()); - Collections.sort(capabilityURIs); - this.capabilityURIs = Collections.unmodifiableSet(new TreeSet<>(capabilityURIs)); - } - - private static Map getCapabilitiesInternal( - NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) { - Map capabilityMap = Maps.newHashMap(); - - for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) { - final Set caps = netconfOperationService.getCapabilities(); - - for (Capability cap : caps) { - - if(capabilityMap.containsKey(cap.getCapabilityUri())) { - LOG.debug("Duplicate capability {} from service {}", cap.getCapabilityUri(), netconfOperationService); - } - - capabilityMap.put(cap.getCapabilityUri(), cap); - } - } - - return capabilityMap; - } - - @Override - public synchronized String getSchemaForCapability(String moduleName, Optional revision) { - - Map> mappedModulesToRevisionToSchema = Maps.newHashMap(); - - for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) { - final Set caps = netconfOperationService.getCapabilities(); - - for (Capability cap : caps) { - if (!cap.getModuleName().isPresent() - || !cap.getRevision().isPresent() - || !cap.getCapabilitySchema().isPresent()){ - continue; - } - - final String currentModuleName = cap.getModuleName().get(); - Map revisionMap = mappedModulesToRevisionToSchema.get(currentModuleName); - if (revisionMap == null) { - revisionMap = Maps.newHashMap(); - mappedModulesToRevisionToSchema.put(currentModuleName, revisionMap); - } - - String currentRevision = cap.getRevision().get(); - revisionMap.put(currentRevision, cap.getCapabilitySchema().get()); - } - } - - Map revisionMapRequest = mappedModulesToRevisionToSchema.get(moduleName); - Preconditions.checkState(revisionMapRequest != null, "Capability for module %s not present, " + "" - + "available modules : %s", moduleName, capabilityURIs); - - if (revision.isPresent()) { - String schema = revisionMapRequest.get(revision.get()); - - Preconditions.checkState(schema != null, - "Capability for module %s:%s not present, available revisions for module: %s", moduleName, - revision.get(), revisionMapRequest.keySet()); - - return schema; - } else { - Preconditions.checkState(revisionMapRequest.size() == 1, - "Expected 1 capability for module %s, available revisions : %s", moduleName, - revisionMapRequest.keySet()); - return revisionMapRequest.values().iterator().next(); - } - } - - @Override - public synchronized Set getCapabilities() { - return capabilityURIs; - } - -} 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 951d0dd98d..9510a61a6e 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 @@ -15,10 +15,10 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfSessionListener; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -31,11 +31,11 @@ import org.w3c.dom.Node; public class NetconfServerSessionListener implements NetconfSessionListener { private static final Logger LOG = LoggerFactory.getLogger(NetconfServerSessionListener.class); - private final SessionMonitoringService monitoringService; + private final NetconfMonitoringService monitoringService; private final NetconfOperationRouter operationRouter; private final AutoCloseable onSessionDownCloseable; - public NetconfServerSessionListener(final NetconfOperationRouter operationRouter, final SessionMonitoringService monitoringService, + public NetconfServerSessionListener(final NetconfOperationRouter operationRouter, NetconfMonitoringService monitoringService, final AutoCloseable onSessionDownCloseable) { this.operationRouter = operationRouter; this.monitoringService = monitoringService; diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java deleted file mode 100644 index 604cc5f55b..0000000000 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.impl; - -import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; -import org.opendaylight.protocol.framework.SessionListenerFactory; - -public class NetconfServerSessionListenerFactory implements SessionListenerFactory { - - private final CommitNotifier commitNotifier; - private final SessionMonitoringService monitor; - private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot; - private final CapabilityProvider capabilityProvider; - - public NetconfServerSessionListenerFactory(final CommitNotifier commitNotifier, - final SessionMonitoringService monitor, - final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, - final CapabilityProvider capabilityProvider) { - - this.commitNotifier = commitNotifier; - this.monitor = monitor; - this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot; - this.capabilityProvider = capabilityProvider; - } - - @Override - public NetconfServerSessionListener getSessionListener() { - NetconfOperationRouter operationRouter = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot, capabilityProvider, commitNotifier); - return new NetconfServerSessionListener(operationRouter, monitor, 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 451c066b77..996bb27587 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 @@ -8,8 +8,6 @@ package org.opendaylight.controller.netconf.impl; -import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider.NetconfOperationProviderUtil.getNetconfSessionIdForReporting; - import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -19,11 +17,12 @@ import io.netty.util.concurrent.Promise; import java.util.Set; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; -import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage; import org.opendaylight.protocol.framework.SessionListenerFactory; import org.opendaylight.protocol.framework.SessionNegotiator; @@ -42,28 +41,28 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF private final Timer timer; private final SessionIdProvider idProvider; - private final NetconfOperationProvider netconfOperationProvider; + private final NetconfOperationServiceFactory aggregatedOpService; private final long connectionTimeoutMillis; private final CommitNotifier commitNotificationProducer; - private final SessionMonitoringService monitoringService; + private final NetconfMonitoringService monitoringService; private static final Logger LOG = LoggerFactory.getLogger(NetconfServerSessionNegotiatorFactory.class); private final Set baseCapabilities; // TODO too many params, refactor - public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider, - SessionIdProvider idProvider, long connectionTimeoutMillis, - CommitNotifier commitNot, - SessionMonitoringService monitoringService) { + public NetconfServerSessionNegotiatorFactory(final Timer timer, final NetconfOperationServiceFactory netconfOperationProvider, + final SessionIdProvider idProvider, final long connectionTimeoutMillis, + final CommitNotifier commitNot, + final NetconfMonitoringService monitoringService) { this(timer, netconfOperationProvider, idProvider, connectionTimeoutMillis, commitNot, monitoringService, DEFAULT_BASE_CAPABILITIES); } // TODO too many params, refactor - public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider, - SessionIdProvider idProvider, long connectionTimeoutMillis, - CommitNotifier commitNot, - SessionMonitoringService monitoringService, Set baseCapabilities) { + public NetconfServerSessionNegotiatorFactory(final Timer timer, final NetconfOperationServiceFactory netconfOperationProvider, + final SessionIdProvider idProvider, final long connectionTimeoutMillis, + final CommitNotifier commitNot, + final NetconfMonitoringService monitoringService, final Set baseCapabilities) { this.timer = timer; - this.netconfOperationProvider = netconfOperationProvider; + this.aggregatedOpService = netconfOperationProvider; this.idProvider = idProvider; this.connectionTimeoutMillis = connectionTimeoutMillis; this.commitNotificationProducer = commitNot; @@ -73,12 +72,12 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF private ImmutableSet validateBaseCapabilities(final Set baseCapabilities) { // Check base capabilities to be supported by the server - Sets.SetView unknownBaseCaps = Sets.difference(baseCapabilities, DEFAULT_BASE_CAPABILITIES); + final Sets.SetView unknownBaseCaps = Sets.difference(baseCapabilities, DEFAULT_BASE_CAPABILITIES); Preconditions.checkArgument(unknownBaseCaps.isEmpty(), "Base capabilities that will be supported by netconf server have to be subset of %s, unknown base capabilities: %s", DEFAULT_BASE_CAPABILITIES, unknownBaseCaps); - ImmutableSet.Builder b = ImmutableSet.builder(); + final ImmutableSet.Builder b = ImmutableSet.builder(); b.addAll(baseCapabilities); // Base 1.0 capability is supported by default b.add(XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0); @@ -95,31 +94,32 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF * @return session negotiator */ @Override - public SessionNegotiator getSessionNegotiator(SessionListenerFactory defunctSessionListenerFactory, - Channel channel, Promise promise) { - long sessionId = idProvider.getNextSessionId(); - NetconfOperationServiceSnapshot netconfOperationServiceSnapshot = netconfOperationProvider.openSnapshot( - getNetconfSessionIdForReporting(sessionId)); - CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot); - - NetconfServerSessionPreferences proposal = null; + public SessionNegotiator getSessionNegotiator(final SessionListenerFactory defunctSessionListenerFactory, + final Channel channel, final Promise promise) { + final long sessionId = idProvider.getNextSessionId(); + + NetconfServerSessionPreferences proposal; try { - proposal = new NetconfServerSessionPreferences( - createHelloMessage(sessionId, capabilityProvider), sessionId); - } catch (NetconfDocumentedException e) { - LOG.error("Unable to create hello mesage for session {} with capability provider {}", sessionId,capabilityProvider); + proposal = new NetconfServerSessionPreferences(createHelloMessage(sessionId, monitoringService), sessionId); + } catch (final NetconfDocumentedException e) { + LOG.error("Unable to create hello message for session {} with {}", sessionId, monitoringService); throw new IllegalStateException(e); } - NetconfServerSessionListenerFactory sessionListenerFactory = new NetconfServerSessionListenerFactory( - commitNotificationProducer, monitoringService, - netconfOperationServiceSnapshot, capabilityProvider); - return new NetconfServerSessionNegotiator(proposal, promise, channel, timer, - sessionListenerFactory.getSessionListener(), connectionTimeoutMillis); + getListener(Long.toString(sessionId)), connectionTimeoutMillis); + } + + private NetconfServerSessionListener getListener(final String netconfSessionIdForReporting) { + final NetconfOperationService service = + this.aggregatedOpService.createService(netconfSessionIdForReporting); + final NetconfOperationRouter operationRouter = + new NetconfOperationRouterImpl(service, commitNotificationProducer, monitoringService, netconfSessionIdForReporting); + return new NetconfServerSessionListener(operationRouter, monitoringService, service); + } - private NetconfHelloMessage createHelloMessage(long sessionId, CapabilityProvider capabilityProvider) throws NetconfDocumentedException { + private NetconfHelloMessage createHelloMessage(final long sessionId, final NetconfMonitoringService capabilityProvider) throws NetconfDocumentedException { return NetconfHelloMessage.createServerHello(Sets.union(capabilityProvider.getCapabilities(), baseCapabilities), sessionId); } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/CapabilityProvider.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/CapabilityProvider.java deleted file mode 100644 index 60cde27fe5..0000000000 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/CapabilityProvider.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.impl.mapping; - -import com.google.common.base.Optional; -import java.util.Set; - -public interface CapabilityProvider { - - String getSchemaForCapability(String moduleName, Optional revision); - - Set getCapabilities(); - -} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java index 742255f973..ca41338c36 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java @@ -11,9 +11,9 @@ package org.opendaylight.controller.netconf.impl.mapping.operations; import com.google.common.base.Preconditions; import java.io.InputStream; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.impl.CommitNotifier; -import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; @@ -32,10 +32,10 @@ public class DefaultCommit extends AbstractNetconfOperation { private static final String NOTIFY_ATTR = "notify"; private final CommitNotifier notificationProducer; - private final CapabilityProvider cap; + private final NetconfMonitoringService cap; private final NetconfOperationRouter operationRouter; - public DefaultCommit(CommitNotifier notifier, CapabilityProvider cap, + public DefaultCommit(CommitNotifier notifier, NetconfMonitoringService cap, String netconfSessionIdForReporting, NetconfOperationRouter netconfOperationRouter) { super(netconfSessionIdForReporting); this.notificationProducer = notifier; diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/AggregatedNetconfOperationServiceFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/AggregatedNetconfOperationServiceFactory.java new file mode 100644 index 0000000000..c299ac7d1a --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/AggregatedNetconfOperationServiceFactory.java @@ -0,0 +1,129 @@ +/* + * 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.impl.osgi; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.controller.netconf.util.CloseableUtil; + +/** + * NetconfOperationService aggregator. Makes a collection of operation services accessible as one. + */ +public class AggregatedNetconfOperationServiceFactory implements NetconfOperationServiceFactory, NetconfOperationServiceFactoryListener { + + private final Set factories = new HashSet<>(); + private final Multimap registrations = HashMultimap.create(); + private final Set listeners = Sets.newHashSet(); + + @Override + public synchronized void onAddNetconfOperationServiceFactory(NetconfOperationServiceFactory service) { + factories.add(service); + + for (final CapabilityListener listener : listeners) { + AutoCloseable reg = service.registerCapabilityListener(listener); + registrations.put(service, reg); + } + } + + @Override + public synchronized void onRemoveNetconfOperationServiceFactory(NetconfOperationServiceFactory service) { + factories.remove(service); + + for (final AutoCloseable autoCloseable : registrations.get(service)) { + try { + autoCloseable.close(); + } catch (Exception e) { + // FIXME Issue warning + } + } + + registrations.removeAll(service); + } + + @Override + public synchronized Set getCapabilities() { + final HashSet capabilities = Sets.newHashSet(); + for (final NetconfOperationServiceFactory factory : factories) { + capabilities.addAll(factory.getCapabilities()); + } + return capabilities; + } + + @Override + public synchronized AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + final Map regs = Maps.newHashMap(); + + for (final NetconfOperationServiceFactory factory : factories) { + final AutoCloseable reg = factory.registerCapabilityListener(listener); + regs.put(factory, reg); + } + listeners.add(listener); + + return new AutoCloseable() { + @Override + public void close() throws Exception { + synchronized (AggregatedNetconfOperationServiceFactory.this) { + listeners.remove(listener); + CloseableUtil.closeAll(regs.values()); + for (final Map.Entry reg : regs.entrySet()) { + registrations.remove(reg.getKey(), reg.getValue()); + } + } + } + }; + } + + @Override + public synchronized NetconfOperationService createService(final String netconfSessionIdForReporting) { + return new AggregatedNetconfOperation(factories, netconfSessionIdForReporting); + } + + private static final class AggregatedNetconfOperation implements NetconfOperationService { + + private final Set services; + + public AggregatedNetconfOperation(final Set factories, final String netconfSessionIdForReporting) { + final Builder b = ImmutableSet.builder(); + for (final NetconfOperationServiceFactory factory : factories) { + b.add(factory.createService(netconfSessionIdForReporting)); + } + this.services = b.build(); + } + + @Override + public Set getNetconfOperations() { + final HashSet operations = Sets.newHashSet(); + for (final NetconfOperationService service : services) { + operations.addAll(service.getNetconfOperations()); + } + return operations; + } + + @Override + public void close() { + try { + CloseableUtil.closeAll(services); + } catch (final Exception e) { + throw new IllegalStateException("Unable to properly close all aggregated services", e); + } + } + } +} 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 a55e32a954..63e837fc18 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 @@ -19,7 +19,6 @@ import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProduce import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -40,7 +39,7 @@ public class NetconfImplActivator implements BundleActivator { @Override public void start(final BundleContext context) { - NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); + AggregatedNetconfOperationServiceFactory factoriesListener = new AggregatedNetconfOperationServiceFactory(); startOperationServiceFactoryTracker(context, factoriesListener); SessionIdProvider idProvider = new SessionIdProvider(); @@ -50,7 +49,7 @@ public class NetconfImplActivator implements BundleActivator { commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); - SessionMonitoringService monitoringService = startMonitoringService(context, factoriesListener); + NetconfMonitoringService monitoringService = startMonitoringService(context, factoriesListener); NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( timer, factoriesListener, idProvider, connectionTimeoutMillis, commitNot, monitoringService); @@ -64,17 +63,14 @@ public class NetconfImplActivator implements BundleActivator { LocalAddress address = NetconfConfigUtil.getNetconfLocalAddress(); LOG.trace("Starting local netconf server at {}", address); dispatch.createLocalServer(address); - - context.registerService(NetconfOperationProvider.class, factoriesListener, null); - } - private void startOperationServiceFactoryTracker(BundleContext context, NetconfOperationServiceFactoryListenerImpl factoriesListener) { + private void startOperationServiceFactoryTracker(BundleContext context, NetconfOperationServiceFactoryListener factoriesListener) { factoriesTracker = new NetconfOperationServiceFactoryTracker(context, factoriesListener); factoriesTracker.open(); } - private NetconfMonitoringServiceImpl startMonitoringService(BundleContext context, NetconfOperationServiceFactoryListenerImpl factoriesListener) { + private NetconfMonitoringServiceImpl startMonitoringService(BundleContext context, AggregatedNetconfOperationServiceFactory factoriesListener) { NetconfMonitoringServiceImpl netconfMonitoringServiceImpl = new NetconfMonitoringServiceImpl(factoriesListener); Dictionary dic = new Hashtable<>(); regMonitoring = context.registerService(NetconfMonitoringService.class, netconfMonitoringServiceImpl, dic); 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 efbe3ad68f..8e5c1a7da3 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 @@ -8,23 +8,24 @@ package org.opendaylight.controller.netconf.impl.osgi; import com.google.common.base.Function; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.Maps; import io.netty.util.internal.ConcurrentSet; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; +import org.opendaylight.controller.netconf.api.Capability; 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.controller.netconf.mapping.api.NetconfOperationServiceFactory; 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; @@ -38,7 +39,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.mon import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, SessionMonitoringService { +public class NetconfMonitoringServiceImpl implements NetconfMonitoringService { + private static final Schema.Location NETCONF_LOCATION = new Schema.Location(Schema.Location.Enumeration.NETCONF); private static final List NETCONF_LOCATIONS = ImmutableList.of(NETCONF_LOCATION); private static final Logger LOG = LoggerFactory.getLogger(NetconfMonitoringServiceImpl.class); @@ -50,10 +52,20 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S }; private final Set sessions = new ConcurrentSet<>(); - private final NetconfOperationProvider netconfOperationProvider; + private final NetconfOperationServiceFactory netconfOperationProvider; + private final Map capabilities = new ConcurrentHashMap<>(); + private static final Function CAPABILITY_TO_URI = new Function() { + @Override + public String apply(final Capability input) { + return input.getCapabilityUri(); + } + }; - public NetconfMonitoringServiceImpl(final NetconfOperationProvider netconfOperationProvider) { + // FIXME check threadsafety + + public NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory netconfOperationProvider) { this.netconfOperationProvider = netconfOperationProvider; + netconfOperationProvider.registerCapabilityListener(this); } @Override @@ -77,38 +89,81 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S @Override public Schemas getSchemas() { - // capabilities should be split from operations (it will allow to move getSchema operation to monitoring module) - try (NetconfOperationServiceSnapshot snapshot = netconfOperationProvider.openSnapshot("netconf-monitoring")) { - return transformSchemas(snapshot.getServices()); - } catch (RuntimeException e) { + try { + return transformSchemas(netconfOperationProvider.getCapabilities()); + } catch (final RuntimeException e) { throw e; - } catch (Exception e) { + } catch (final Exception e) { throw new IllegalStateException("Exception while closing", e); } } - private static Schemas transformSchemas(final Set services) { - // FIXME: Capability implementations do not have hashcode/equals! - final Set caps = new HashSet<>(); - 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()); + @Override + public String getSchemaForCapability(final String moduleName, final Optional revision) { + + // FIXME not effective at all + + Map> mappedModulesToRevisionToSchema = Maps.newHashMap(); + + final Collection caps = capabilities.values(); + + for (Capability cap : caps) { + if (!cap.getModuleName().isPresent() + || !cap.getRevision().isPresent() + || !cap.getCapabilitySchema().isPresent()){ + continue; + } + + final String currentModuleName = cap.getModuleName().get(); + Map revisionMap = mappedModulesToRevisionToSchema.get(currentModuleName); + if (revisionMap == null) { + revisionMap = Maps.newHashMap(); + mappedModulesToRevisionToSchema.put(currentModuleName, revisionMap); + } + + String currentRevision = cap.getRevision().get(); + revisionMap.put(currentRevision, cap.getCapabilitySchema().get()); + } + + Map revisionMapRequest = mappedModulesToRevisionToSchema.get(moduleName); + Preconditions.checkState(revisionMapRequest != null, "Capability for module %s not present, " + "" + + "available modules : %s", moduleName, Collections2.transform(caps, CAPABILITY_TO_URI)); + + if (revision.isPresent()) { + String schema = revisionMapRequest.get(revision.get()); + + Preconditions.checkState(schema != null, + "Capability for module %s:%s not present, available revisions for module: %s", moduleName, + revision.get(), revisionMapRequest.keySet()); + + return schema; + } else { + Preconditions.checkState(revisionMapRequest.size() == 1, + "Expected 1 capability for module %s, available revisions : %s", moduleName, + revisionMapRequest.keySet()); + return revisionMapRequest.values().iterator().next(); } + } + + @Override + public Set getCapabilities() { + return capabilities.keySet(); + } + private static Schemas transformSchemas(final Set caps) { final List schemas = new ArrayList<>(caps.size()); - for (Capability cap : caps) { + for (final Capability cap : caps) { if (cap.getCapabilitySchema().isPresent()) { - SchemaBuilder builder = new SchemaBuilder(); + final SchemaBuilder builder = new SchemaBuilder(); Preconditions.checkState(cap.getModuleNamespace().isPresent()); builder.setNamespace(new Uri(cap.getModuleNamespace().get())); Preconditions.checkState(cap.getRevision().isPresent()); - String version = cap.getRevision().get(); + final String version = cap.getRevision().get(); builder.setVersion(version); Preconditions.checkState(cap.getModuleName().isPresent()); - String identifier = cap.getModuleName().get(); + final String identifier = cap.getModuleName().get(); builder.setIdentifier(identifier); builder.setFormat(Yang.class); @@ -132,10 +187,23 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, S final Builder b = ImmutableList.builder(); b.add(NETCONF_LOCATION); - for (String location : locations) { + for (final String location : locations) { b.add(new Schema.Location(new Uri(location))); } return b.build(); } + + @Override + public void onCapabilitiesAdded(final Set addedCaps) { + // FIXME what check for duplicates + this.capabilities.putAll(Maps.uniqueIndex(addedCaps, CAPABILITY_TO_URI)); + } + + @Override + public void onCapabilitiesRemoved(final Set addedCaps) { + for (final Capability addedCap : addedCaps) { + capabilities.remove(addedCap.getCapabilityUri()); + } + } } 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 c8fa341747..fb5a2b325e 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 @@ -17,12 +17,11 @@ import java.util.NavigableMap; import java.util.Set; import java.util.TreeMap; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.impl.CommitNotifier; import org.opendaylight.controller.netconf.impl.NetconfServerSession; -import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit; -import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi; @@ -30,7 +29,6 @@ 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.mapping.api.SessionAwareNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.slf4j.Logger; @@ -40,29 +38,20 @@ import org.w3c.dom.Document; public class NetconfOperationRouterImpl implements NetconfOperationRouter { private static final Logger LOG = LoggerFactory.getLogger(NetconfOperationRouterImpl.class); - private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot; + private final NetconfOperationService netconfOperationServiceSnapshot; private final Collection allNetconfOperations; - public NetconfOperationRouterImpl(final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, final CapabilityProvider capabilityProvider, - final CommitNotifier commitNotifier) { + public NetconfOperationRouterImpl(final NetconfOperationService netconfOperationServiceSnapshot, + final CommitNotifier commitNotifier, final NetconfMonitoringService netconfMonitoringService, final String sessionId) { this.netconfOperationServiceSnapshot = Preconditions.checkNotNull(netconfOperationServiceSnapshot); - final String sessionId = netconfOperationServiceSnapshot.getNetconfSessionIdForReporting(); - final Set ops = new HashSet<>(); - ops.add(new DefaultGetSchema(capabilityProvider, sessionId)); ops.add(new DefaultCloseSession(sessionId, this)); ops.add(new DefaultStartExi(sessionId)); ops.add(new DefaultStopExi(sessionId)); - ops.add(new DefaultCommit(commitNotifier, capabilityProvider, sessionId, this)); + ops.add(new DefaultCommit(commitNotifier, netconfMonitoringService, sessionId, this)); - for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) { - for (NetconfOperation netconfOperation : netconfOperationService.getNetconfOperations()) { - Preconditions.checkState(!ops.contains(netconfOperation), - "Netconf operation %s already present", netconfOperation); - ops.add(netconfOperation); - } - } + ops.addAll(netconfOperationServiceSnapshot.getNetconfOperations()); allNetconfOperations = ImmutableSet.copyOf(ops); } 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 deleted file mode 100644 index 6c55c35e25..0000000000 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.impl.osgi; - -import java.util.HashSet; -import java.util.Set; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; - -public class NetconfOperationServiceFactoryListenerImpl implements NetconfOperationServiceFactoryListener, - NetconfOperationProvider { - private final Set allFactories = new HashSet<>(); - - @Override - public synchronized void onAddNetconfOperationServiceFactory(NetconfOperationServiceFactory service) { - allFactories.add(service); - } - - @Override - public synchronized void onRemoveNetconfOperationServiceFactory(NetconfOperationServiceFactory service) { - allFactories.remove(service); - } - - @Override - public synchronized NetconfOperationServiceSnapshotImpl openSnapshot(String sessionIdForReporting) { - return new NetconfOperationServiceSnapshotImpl(allFactories, sessionIdForReporting); - } - -} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java deleted file mode 100644 index 26abdd974d..0000000000 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.impl.osgi; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSet.Builder; -import java.util.Set; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot; -import org.opendaylight.controller.netconf.util.CloseableUtil; - -public class NetconfOperationServiceSnapshotImpl implements NetconfOperationServiceSnapshot { - - private final Set services; - private final String netconfSessionIdForReporting; - - public NetconfOperationServiceSnapshotImpl(final Set factories, final String sessionIdForReporting) { - final Builder b = ImmutableSet.builder(); - netconfSessionIdForReporting = sessionIdForReporting; - for (NetconfOperationServiceFactory factory : factories) { - b.add(factory.createService(netconfSessionIdForReporting)); - } - this.services = b.build(); - } - - @Override - public String getNetconfSessionIdForReporting() { - return netconfSessionIdForReporting; - } - - @Override - public Set getServices() { - return services; - } - - @Override - public void close() throws Exception { - CloseableUtil.closeAll(services); - } - - @Override - public String toString() { - return "NetconfOperationServiceSnapshotImpl{" + netconfSessionIdForReporting + '}'; - } -} diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java index 8e8a73b914..36dfb6f31b 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import com.google.common.base.Preconditions; @@ -48,8 +49,11 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.opendaylight.controller.netconf.api.Capability; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; @@ -57,9 +61,7 @@ import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionList import org.opendaylight.controller.netconf.client.TestingNetconfClient; import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; -import org.opendaylight.controller.netconf.mapping.api.Capability; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; @@ -115,10 +117,11 @@ public class ConcurrentClientsTest { HashedWheelTimer hashedWheelTimer; private TestingNetconfOperation testingNetconfOperation; - public static SessionMonitoringService createMockedMonitoringService() { - SessionMonitoringService monitoring = mock(SessionMonitoringService.class); + public static NetconfMonitoringService createMockedMonitoringService() { + NetconfMonitoringService monitoring = mock(NetconfMonitoringService.class); doNothing().when(monitoring).onSessionUp(any(NetconfServerSession.class)); doNothing().when(monitoring).onSessionDown(any(NetconfServerSession.class)); + doReturn(Collections.emptySet()).when(monitoring).getCapabilities(); return monitoring; } @@ -143,7 +146,7 @@ public class ConcurrentClientsTest { nettyGroup = new NioEventLoopGroup(nettyThreads); netconfClientDispatcher = new NetconfClientDispatcherImpl(nettyGroup, nettyGroup, hashedWheelTimer); - NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); + AggregatedNetconfOperationServiceFactory factoriesListener = new AggregatedNetconfOperationServiceFactory(); testingNetconfOperation = new TestingNetconfOperation(); factoriesListener.onAddNetconfOperationServiceFactory(new TestingOperationServiceFactory(testingNetconfOperation)); @@ -259,13 +262,22 @@ public class ConcurrentClientsTest { this.operations = operations; } + @Override + public Set getCapabilities() { + return Collections.emptySet(); + } + + @Override + public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + return new AutoCloseable(){ + @Override + public void close() throws Exception {} + }; + } + @Override public NetconfOperationService createService(String netconfSessionIdForReporting) { return new NetconfOperationService() { - @Override - public Set getCapabilities() { - return Collections.emptySet(); - } @Override public Set getNetconfOperations() { 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 df4069ac17..4fd04e29ef 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 @@ -17,7 +17,7 @@ import java.net.InetSocketAddress; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; public class NetconfDispatcherImplTest { @@ -33,7 +33,7 @@ public class NetconfDispatcherImplTest { commitNot = new DefaultCommitNotificationProducer( ManagementFactory.getPlatformMBeanServer()); - NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); + AggregatedNetconfOperationServiceFactory factoriesListener = new AggregatedNetconfOperationServiceFactory(); SessionIdProvider idProvider = new SessionIdProvider(); hashedWheelTimer = new HashedWheelTimer(); diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfMonitoringServiceImplTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfMonitoringServiceImplTest.java index 93caa09286..fed4742dd8 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfMonitoringServiceImplTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfMonitoringServiceImplTest.java @@ -8,107 +8,7 @@ package org.opendaylight.controller.netconf.impl; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.google.common.base.Optional; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import io.netty.channel.Channel; -import java.util.Set; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; -import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -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.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; - public class NetconfMonitoringServiceImplTest { - private NetconfMonitoringServiceImpl service; - - @Mock - private NetconfOperationProvider operationProvider; - @Mock - private NetconfManagementSession managementSession; - @Mock - private NetconfOperationServiceSnapshot snapshot; - @Mock - private NetconfOperationService operationService; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - service = new NetconfMonitoringServiceImpl(operationProvider); - } - - @Test - public void testSessions() throws Exception { - doReturn("sessToStr").when(managementSession).toString(); - service.onSessionUp(managementSession); - } - - @Test(expected = RuntimeException.class) - public void testGetSchemas() throws Exception { - doThrow(RuntimeException.class).when(operationProvider).openSnapshot(anyString()); - service.getSchemas(); - } - - @Test(expected = IllegalStateException.class) - public void testGetSchemas2() throws Exception { - doThrow(Exception.class).when(operationProvider).openSnapshot(anyString()); - service.getSchemas(); - } - - @Test - public void testGetSchemas3() throws Exception { - doReturn("").when(managementSession).toString(); - Capability cap = mock(Capability.class); - Set caps = Sets.newHashSet(cap); - Set services = Sets.newHashSet(operationService); - doReturn(snapshot).when(operationProvider).openSnapshot(anyString()); - doReturn(services).when(snapshot).getServices(); - doReturn(caps).when(operationService).getCapabilities(); - Optional opt = mock(Optional.class); - doReturn(opt).when(cap).getCapabilitySchema(); - doReturn(true).when(opt).isPresent(); - doReturn(opt).when(cap).getModuleNamespace(); - doReturn("namespace").when(opt).get(); - Optional optRev = Optional.of("rev"); - doReturn(optRev).when(cap).getRevision(); - doReturn(Optional.of("modName")).when(cap).getModuleName(); - doReturn(Lists.newArrayList("loc")).when(cap).getLocation(); - doNothing().when(snapshot).close(); - - assertNotNull(service.getSchemas()); - verify(snapshot, times(1)).close(); - - NetconfServerSessionListener sessionListener = mock(NetconfServerSessionListener.class); - Channel channel = mock(Channel.class); - doReturn("mockChannel").when(channel).toString(); - NetconfHelloMessageAdditionalHeader header = new NetconfHelloMessageAdditionalHeader("name", "addr", "2", "tcp", "id"); - NetconfServerSession sm = new NetconfServerSession(sessionListener, channel, 10, header); - doNothing().when(sessionListener).onSessionUp(any(NetconfServerSession.class)); - sm.sessionUp(); - service.onSessionUp(sm); - assertEquals(1, service.getSessions().getSession().size()); - - assertEquals(Long.valueOf(10), service.getSessions().getSession().get(0).getSessionId()); - - service.onSessionDown(sm); - assertEquals(0, service.getSessions().getSession().size()); - } + // TODO redo test } diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommitTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommitTest.java index 15aeb8d27c..aa8c0a0f60 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommitTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommitTest.java @@ -22,9 +22,9 @@ import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerSession; -import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; @@ -38,7 +38,7 @@ public class DefaultCommitTest { private Document requestMessage; private NetconfOperationRouter router; private DefaultCommitNotificationProducer notifier; - private CapabilityProvider cap; + private NetconfMonitoringService cap; private DefaultCommit commit; @Before @@ -49,7 +49,7 @@ public class DefaultCommitTest { doReturn(false).when(operation).isExecutionTermination(); notifier = mock(DefaultCommitNotificationProducer.class); doNothing().when(notifier).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class)); - cap = mock(CapabilityProvider.class); + cap = mock(NetconfMonitoringService.class); doReturn(Sets.newHashSet()).when(cap).getCapabilities(); Document rpcData = XmlFileLoader.xmlFileToDocument("netconfMessages/editConfig_expectedResult.xml"); doReturn(rpcData).when(router).onNetconfMessage(any(Document.class), any(NetconfServerSession.class)); diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivatorTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivatorTest.java index 413c9cc945..2fb989507c 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivatorTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivatorTest.java @@ -12,7 +12,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.util.Arrays; @@ -44,11 +43,11 @@ public class NetconfImplActivatorTest { doReturn(filter).when(bundle).createFilter(anyString()); doNothing().when(bundle).addServiceListener(any(ServiceListener.class), anyString()); - ServiceReference[] refs = new ServiceReference[0]; + ServiceReference[] refs = {}; doReturn(refs).when(bundle).getServiceReferences(anyString(), anyString()); doReturn(Arrays.asList(refs)).when(bundle).getServiceReferences(any(Class.class), anyString()); doReturn("").when(bundle).getProperty(anyString()); - doReturn(registration).when(bundle).registerService(any(Class.class), any(NetconfOperationServiceFactoryListenerImpl.class), any(Dictionary.class)); + doReturn(registration).when(bundle).registerService(any(Class.class), any(AggregatedNetconfOperationServiceFactory.class), any(Dictionary.class)); doNothing().when(registration).unregister(); doNothing().when(bundle).removeServiceListener(any(ServiceListener.class)); } @@ -57,7 +56,7 @@ public class NetconfImplActivatorTest { public void testStart() throws Exception { NetconfImplActivator activator = new NetconfImplActivator(); activator.start(bundle); - verify(bundle, times(2)).registerService(any(Class.class), any(NetconfOperationServiceFactoryListenerImpl.class), any(Dictionary.class)); + verify(bundle).registerService(any(Class.class), any(AggregatedNetconfOperationServiceFactory.class), any(Dictionary.class)); activator.stop(bundle); } } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java index b70e97bac9..c2812dbf61 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java @@ -13,7 +13,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anySetOf; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import io.netty.channel.Channel; @@ -47,6 +46,7 @@ import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesMod import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory; import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; @@ -57,13 +57,11 @@ import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProduce import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; -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.monitoring.osgi.NetconfMonitoringActivator; +import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService; import org.opendaylight.controller.netconf.notifications.BaseNetconfNotificationListener; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.protocol.framework.NeverReconnectStrategy; @@ -108,14 +106,16 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { setUpTestInitial(); - final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); + final AggregatedNetconfOperationServiceFactory factoriesListener = new AggregatedNetconfOperationServiceFactory(); + final NetconfMonitoringService netconfMonitoringService = getNetconfMonitoringService(factoriesListener); factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore())); + factoriesListener.onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(new NetconfMonitoringOperationService(netconfMonitoringService))); - for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories()) { + for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories(factoriesListener)) { factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory); } - serverTcpChannel = startNetconfTcpServer(factoriesListener); + serverTcpChannel = startNetconfTcpServer(factoriesListener, netconfMonitoringService); clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer()); } @@ -137,8 +137,8 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { return get; } - private Channel startNetconfTcpServer(final NetconfOperationServiceFactoryListenerImpl factoriesListener) throws Exception { - final NetconfServerDispatcherImpl dispatch = createDispatcher(factoriesListener, getNetconfMonitoringService(), getNotificationProducer()); + private Channel startNetconfTcpServer(final AggregatedNetconfOperationServiceFactory listener, final NetconfMonitoringService monitoring) throws Exception { + final NetconfServerDispatcherImpl dispatch = createDispatcher(listener, monitoring, getNotificationProducer()); final ChannelFuture s; if(getTcpServerAddress() instanceof LocalAddress) { @@ -157,16 +157,12 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { return notificationProducer; } - protected Iterable getAdditionalServiceFactories() { + protected Iterable getAdditionalServiceFactories(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception { return Collections.emptySet(); } - protected SessionMonitoringService getNetconfMonitoringService() throws Exception { - final NetconfOperationProvider netconfOperationProvider = mock(NetconfOperationProvider.class); - final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class); - doReturn(Collections.emptySet()).when(snap).getServices(); - doReturn(snap).when(netconfOperationProvider).openSnapshot(anyString()); - return new NetconfMonitoringServiceImpl(netconfOperationProvider); + protected NetconfMonitoringService getNetconfMonitoringService(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception { + return new NetconfMonitoringServiceImpl(factoriesListener); } protected abstract SocketAddress getTcpServerAddress(); @@ -206,7 +202,7 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { } protected NetconfServerDispatcherImpl createDispatcher( - final NetconfOperationServiceFactoryListenerImpl factoriesListener, final SessionMonitoringService sessionMonitoringService, + final AggregatedNetconfOperationServiceFactory factoriesListener, final NetconfMonitoringService sessionMonitoringService, final DefaultCommitNotificationProducer commitNotifier) { final SessionIdProvider idProvider = new SessionIdProvider(); 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 92c96d92f2..379c23af3c 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 @@ -9,23 +9,18 @@ package org.opendaylight.controller.netconf.it; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithName; import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertElementsCount; import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToDocument; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.Collections; import java.util.List; -import java.util.Set; import javax.management.InstanceNotFoundException; import javax.management.Notification; import javax.management.NotificationListener; @@ -38,15 +33,6 @@ import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification; import org.opendaylight.controller.netconf.client.TestingNetconfClient; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; -import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -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.NetconfOperationProvider; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; -import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator; -import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService; import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.w3c.dom.Document; @@ -58,29 +44,12 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { public static final int PORT = 12026; private static final InetSocketAddress TCP_ADDRESS = new InetSocketAddress(LOOPBACK_ADDRESS, PORT); - private NetconfMonitoringServiceImpl netconfMonitoringService; - - @Override - protected void setUpTestInitial() { - netconfMonitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider()); - } - - @Override - protected SessionMonitoringService getNetconfMonitoringService() throws Exception { - return netconfMonitoringService; - } @Override protected SocketAddress getTcpServerAddress() { return TCP_ADDRESS; } - @Override - protected Iterable getAdditionalServiceFactories() { - return Collections.singletonList(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory( - new NetconfMonitoringOperationService(netconfMonitoringService))); - } - @Override protected DefaultCommitNotificationProducer getNotificationProducer() { return new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); @@ -95,7 +64,6 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { try (ConfigPersisterNotificationHandler configPersisterNotificationHandler = new ConfigPersisterNotificationHandler( platformMBeanServer, mockedAggregator)) { - try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 4000))) { NetconfMessage response = netconfClient.sendMessage(loadGetConfigMessage()); assertContainsElementWithName(response.getDocument(), "modules"); @@ -143,20 +111,6 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml"); } - - public NetconfOperationProvider getNetconfOperationProvider() { - final NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class); - final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class); - final NetconfOperationService service = mock(NetconfOperationService.class); - final Set caps = Sets.newHashSet(); - doReturn(caps).when(service).getCapabilities(); - final Set services = Sets.newHashSet(service); - doReturn(services).when(snap).getServices(); - doReturn(snap).when(factoriesListener).openSnapshot(anyString()); - - return factoriesListener; - } - private static class VerifyingNotificationListener implements NotificationListener { public List notifications = Lists.newArrayList(); diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java index ea94fd3f8b..e745b393fb 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.netconf.it; import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -26,21 +27,14 @@ import java.util.Collections; import java.util.List; import java.util.Set; import org.junit.Test; +import org.opendaylight.controller.netconf.api.Capability; import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; import org.opendaylight.controller.netconf.client.TestingNetconfClient; -import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -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.NetconfOperationProvider; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; -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.w3c.dom.Document; public class NetconfITMonitoringTest extends AbstractNetconfConfigTest { @@ -49,45 +43,11 @@ public class NetconfITMonitoringTest extends AbstractNetconfConfigTest { public static final InetSocketAddress TCP_ADDRESS = new InetSocketAddress(LOOPBACK_ADDRESS, PORT); public static final TestingCapability TESTING_CAPABILITY = new TestingCapability(); - private NetconfMonitoringServiceImpl netconfMonitoringService; - - @Override - protected void setUpTestInitial() { - netconfMonitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider()); - } - - @Override - protected SessionMonitoringService getNetconfMonitoringService() throws Exception { - return netconfMonitoringService; - } - - @Override - protected Iterable getAdditionalServiceFactories() { - return Collections.singletonList(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory( - new NetconfMonitoringOperationService(netconfMonitoringService))); - } - @Override protected InetSocketAddress getTcpServerAddress() { return TCP_ADDRESS; } - static SessionMonitoringService getNetconfMonitoringListenerService(final Logger LOG, final NetconfMonitoringServiceImpl monitor) { - return new SessionMonitoringService() { - @Override - public void onSessionUp(final NetconfManagementSession session) { - LOG.debug("Management session up {}", session); - monitor.onSessionUp(session); - } - - @Override - public void onSessionDown(final NetconfManagementSession session) { - LOG.debug("Management session down {}", session); - monitor.onSessionDown(session); - } - }; - } - @Test public void testGetResponseFromMonitoring() throws Exception { try (TestingNetconfClient netconfClient = new TestingNetconfClient("client-monitoring", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 10000))) { @@ -151,23 +111,24 @@ public class NetconfITMonitoringTest extends AbstractNetconfConfigTest { assertEquals("Incorrect number of session-id tags in " + XmlUtil.toString(document), i, elementSize); } - public static NetconfOperationProvider getNetconfOperationProvider() { - final NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class); - final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class); + public static AggregatedNetconfOperationServiceFactory getNetconfOperationProvider() throws Exception { + final AggregatedNetconfOperationServiceFactory factoriesListener = mock(AggregatedNetconfOperationServiceFactory.class); + final NetconfOperationService snap = mock(NetconfOperationService.class); try { doNothing().when(snap).close(); } catch (final Exception e) { // not happening throw new IllegalStateException(e); } - final NetconfOperationService service = mock(NetconfOperationService.class); final Set caps = Sets.newHashSet(); caps.add(TESTING_CAPABILITY); - doReturn(caps).when(service).getCapabilities(); - final Set services = Sets.newHashSet(service); - doReturn(services).when(snap).getServices(); - doReturn(snap).when(factoriesListener).openSnapshot(anyString()); + doReturn(caps).when(factoriesListener).getCapabilities(); + doReturn(snap).when(factoriesListener).createService(anyString()); + + AutoCloseable mock = mock(AutoCloseable.class); + doNothing().when(mock).close(); + doReturn(mock).when(factoriesListener).registerCapabilityListener(any(CapabilityListener.class)); 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 deleted file mode 100644 index f5c50f8167..0000000000 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 openSnapshot(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/NetconfOperationService.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java index 5e2cba2cba..1a1a124895 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java @@ -15,11 +15,6 @@ import java.util.Set; */ public interface NetconfOperationService extends AutoCloseable { - /** - * Get capabilities announced by server hello message. - */ - Set getCapabilities(); - /** * Get set of netconf operations that are handled by this service. */ diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactory.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactory.java index 81401f26ee..8caa177bfa 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactory.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactory.java @@ -8,6 +8,10 @@ package org.opendaylight.controller.netconf.mapping.api; +import java.util.Set; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; + /** * Factory that must be registered in OSGi service registry in order to be used * by netconf-impl. Responsible for creating per-session instances of @@ -15,6 +19,16 @@ package org.opendaylight.controller.netconf.mapping.api; */ public interface NetconfOperationServiceFactory { + /** + * Get capabilities supported by current operation service. + */ + Set getCapabilities(); + + /** + * Supported capabilities may change over time, registering a listener allows for push based information retrieval about current notifications + */ + AutoCloseable registerCapabilityListener(CapabilityListener listener); + NetconfOperationService createService(String netconfSessionIdForReporting); } 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 deleted file mode 100644 index eaa69379f7..0000000000 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceSnapshot.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/GetSchema.java similarity index 75% rename from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java rename to opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/GetSchema.java index 5310704876..d02cb432cb 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/GetSchema.java @@ -1,19 +1,19 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2015 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.impl.mapping.operations; +package org.opendaylight.controller.netconf.monitoring; import com.google.common.base.Optional; import com.google.common.collect.Maps; import java.util.Map; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; -import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -23,16 +23,16 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -public final class DefaultGetSchema extends AbstractLastNetconfOperation { +public class GetSchema extends AbstractLastNetconfOperation { public static final String GET_SCHEMA = "get-schema"; public static final String IDENTIFIER = "identifier"; public static final String VERSION = "version"; - private static final Logger LOG = LoggerFactory.getLogger(DefaultGetSchema.class); - private final CapabilityProvider cap; + private static final Logger LOG = LoggerFactory.getLogger(GetSchema.class); + private final NetconfMonitoringService cap; - public DefaultGetSchema(CapabilityProvider cap, String netconfSessionIdForReporting) { - super(netconfSessionIdForReporting); + public GetSchema(final NetconfMonitoringService cap) { + super(MonitoringConstants.MODULE_NAME); this.cap = cap; } @@ -47,16 +47,16 @@ public final class DefaultGetSchema extends AbstractLastNetconfOperation { } @Override - protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { - GetSchemaEntry entry; + protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement xml) throws NetconfDocumentedException { + final GetSchemaEntry entry; entry = new GetSchemaEntry(xml); - String schema; + final String schema; try { schema = cap.getSchemaForCapability(entry.identifier, entry.version); - } catch (IllegalStateException e) { - Map errorInfo = Maps.newHashMap(); + } catch (final IllegalStateException e) { + final Map errorInfo = Maps.newHashMap(); errorInfo.put(entry.identifier, e.getMessage()); LOG.warn("Rpc error: {}", NetconfDocumentedException.ErrorTag.operation_failed, e); throw new NetconfDocumentedException(e.getMessage(), NetconfDocumentedException.ErrorType.application, @@ -64,7 +64,7 @@ public final class DefaultGetSchema extends AbstractLastNetconfOperation { NetconfDocumentedException.ErrorSeverity.error, errorInfo); } - Element getSchemaResult; + final Element getSchemaResult; getSchemaResult = XmlUtil.createTextElement(document, XmlNetconfConstants.DATA_KEY, schema, Optional.of(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING)); LOG.trace("{} operation successful", GET_SCHEMA); @@ -76,19 +76,19 @@ public final class DefaultGetSchema extends AbstractLastNetconfOperation { private final String identifier; private final Optional version; - GetSchemaEntry(XmlElement getSchemaElement) throws NetconfDocumentedException { + GetSchemaEntry(final XmlElement getSchemaElement) throws NetconfDocumentedException { getSchemaElement.checkName(GET_SCHEMA); getSchemaElement.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING); XmlElement identifierElement = null; try { identifierElement = getSchemaElement.getOnlyChildElementWithSameNamespace(IDENTIFIER); - } catch (MissingNameSpaceException e) { + } catch (final MissingNameSpaceException e) { LOG.trace("Can't get identifier element as only child element with same namespace due to ",e); throw NetconfDocumentedException.wrap(e); } identifier = identifierElement.getTextContent(); - Optional versionElement = getSchemaElement + final Optional versionElement = getSchemaElement .getOnlyChildElementWithSameNamespaceOptionally(VERSION); if (versionElement.isPresent()) { version = Optional.of(versionElement.get().getTextContent()); diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringActivator.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringActivator.java index 1411350cd3..1b0a50b830 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringActivator.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringActivator.java @@ -7,8 +7,18 @@ */ package org.opendaylight.controller.netconf.monitoring.osgi; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.controller.netconf.monitoring.MonitoringConstants; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.slf4j.Logger; @@ -31,22 +41,84 @@ public class NetconfMonitoringActivator implements BundleActivator { if(monitor!=null) { try { monitor.close(); - } catch (Exception e) { + } catch (final Exception e) { LOG.warn("Ignoring exception while closing {}", monitor, e); } } } - public static class NetconfMonitoringOperationServiceFactory implements NetconfOperationServiceFactory { + public static class NetconfMonitoringOperationServiceFactory implements NetconfOperationServiceFactory, AutoCloseable { + private final NetconfMonitoringOperationService operationService; - public NetconfMonitoringOperationServiceFactory(NetconfMonitoringOperationService operationService) { + private static final Set CAPABILITIES = Sets.newHashSet(new Capability() { + + @Override + public String getCapabilityUri() { + return MonitoringConstants.URI; + } + + @Override + public Optional getModuleNamespace() { + return Optional.of(MonitoringConstants.NAMESPACE); + } + + @Override + public Optional getModuleName() { + return Optional.of(MonitoringConstants.MODULE_NAME); + } + + @Override + public Optional getRevision() { + return Optional.of(MonitoringConstants.MODULE_REVISION); + } + + @Override + public Optional getCapabilitySchema() { + return Optional.absent(); + } + + @Override + public Collection getLocation() { + return Collections.emptyList(); + } + }); + + private static final AutoCloseable AUTO_CLOSEABLE = new AutoCloseable() { + @Override + public void close() throws Exception { + // NOOP + } + }; + + private final List listeners = new ArrayList<>(); + + public NetconfMonitoringOperationServiceFactory(final NetconfMonitoringOperationService operationService) { this.operationService = operationService; } @Override - public NetconfOperationService createService(String netconfSessionIdForReporting) { + public NetconfOperationService createService(final String netconfSessionIdForReporting) { return operationService; } + + @Override + public Set getCapabilities() { + return CAPABILITIES; + } + + @Override + public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + listener.onCapabilitiesAdded(getCapabilities()); + listeners.add(listener); + return AUTO_CLOSEABLE; + } + + @Override + public void close() { + for (final CapabilityListener listener : listeners) { + listener.onCapabilitiesRemoved(getCapabilities()); + } + } } } diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java index a17e139131..efe71e9127 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java @@ -7,67 +7,25 @@ */ package org.opendaylight.controller.netconf.monitoring.osgi; -import com.google.common.base.Optional; import com.google.common.collect.Sets; -import java.util.Collection; -import java.util.Collections; import java.util.Set; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.monitoring.Get; -import org.opendaylight.controller.netconf.monitoring.MonitoringConstants; +import org.opendaylight.controller.netconf.monitoring.GetSchema; public class NetconfMonitoringOperationService implements NetconfOperationService { - private static final Set CAPABILITIES = Sets.newHashSet(new Capability() { - - @Override - public String getCapabilityUri() { - return MonitoringConstants.URI; - } - - @Override - public Optional getModuleNamespace() { - return Optional.of(MonitoringConstants.NAMESPACE); - } - - @Override - public Optional getModuleName() { - return Optional.of(MonitoringConstants.MODULE_NAME); - } - - @Override - public Optional getRevision() { - return Optional.of(MonitoringConstants.MODULE_REVISION); - } - - @Override - public Optional getCapabilitySchema() { - return Optional.absent(); - } - - @Override - public Collection getLocation() { - return Collections.emptyList(); - } - }); - private final NetconfMonitoringService monitor; public NetconfMonitoringOperationService(final NetconfMonitoringService monitor) { this.monitor = monitor; } - @Override - public Set getCapabilities() { - return CAPABILITIES; - } - @Override public Set getNetconfOperations() { - return Sets.newHashSet(new Get(monitor)); + return Sets.newHashSet(new Get(monitor), new GetSchema(monitor)); } @Override diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java index 9e7c105aa4..5d0a2a91ad 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java @@ -25,6 +25,7 @@ public class NetconfMonitoringServiceTracker extends ServiceTracker reg; + private NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory factory; NetconfMonitoringServiceTracker(final BundleContext context) { super(context, NetconfMonitoringService.class, null); @@ -38,7 +39,7 @@ public class NetconfMonitoringServiceTracker extends ServiceTracker properties = new Hashtable<>(); @@ -58,6 +59,9 @@ public class NetconfMonitoringServiceTracker extends ServiceTracker\n" + " threadpool-api\n" + @@ -45,15 +46,16 @@ public class DefaultGetSchemaTest { @Test(expected = NetconfDocumentedException.class) public void testDefaultGetSchema() throws Exception { - DefaultGetSchema schema = new DefaultGetSchema(cap, ""); + GetSchema schema = new GetSchema(cap); doThrow(IllegalStateException.class).when(cap).getSchemaForCapability(anyString(), any(Optional.class)); schema.handleWithNoSubsequentOperations(doc, XmlElement.fromDomElement(XmlUtil.readXmlToElement(getSchema))); } @Test public void handleWithNoSubsequentOperations() throws Exception { - DefaultGetSchema schema = new DefaultGetSchema(cap, ""); + GetSchema schema = new GetSchema(cap); doReturn("").when(cap).getSchemaForCapability(anyString(), any(Optional.class)); assertNotNull(schema.handleWithNoSubsequentOperations(doc, XmlElement.fromDomElement(XmlUtil.readXmlToElement(getSchema)))); } -} + +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationServiceTest.java b/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationServiceTest.java index 7873183188..3a0362277e 100644 --- a/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationServiceTest.java +++ b/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationServiceTest.java @@ -22,14 +22,15 @@ public class NetconfMonitoringOperationServiceTest { public void testGetters() throws Exception { NetconfMonitoringService monitor = mock(NetconfMonitoringService.class); NetconfMonitoringOperationService service = new NetconfMonitoringOperationService(monitor); + NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory serviceFactory = new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(service); - assertEquals(1, service.getNetconfOperations().size()); + assertEquals(2, service.getNetconfOperations().size()); - assertEquals(Optional.absent(), service.getCapabilities().iterator().next().getCapabilitySchema()); - assertEquals(Collections.emptyList(), service.getCapabilities().iterator().next().getLocation()); - assertEquals(Optional.of(MonitoringConstants.MODULE_REVISION), service.getCapabilities().iterator().next().getRevision()); - assertEquals(Optional.of(MonitoringConstants.MODULE_NAME), service.getCapabilities().iterator().next().getModuleName()); - assertEquals(Optional.of(MonitoringConstants.NAMESPACE), service.getCapabilities().iterator().next().getModuleNamespace()); - assertEquals(MonitoringConstants.URI, service.getCapabilities().iterator().next().getCapabilityUri()); + assertEquals(Optional.absent(), serviceFactory.getCapabilities().iterator().next().getCapabilitySchema()); + assertEquals(Collections.emptyList(), serviceFactory.getCapabilities().iterator().next().getLocation()); + assertEquals(Optional.of(MonitoringConstants.MODULE_REVISION), serviceFactory.getCapabilities().iterator().next().getRevision()); + assertEquals(Optional.of(MonitoringConstants.MODULE_NAME), serviceFactory.getCapabilities().iterator().next().getModuleName()); + assertEquals(Optional.of(MonitoringConstants.NAMESPACE), serviceFactory.getCapabilities().iterator().next().getModuleNamespace()); + assertEquals(MonitoringConstants.URI, serviceFactory.getCapabilities().iterator().next().getCapabilityUri()); } } diff --git a/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java b/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java index 4b5dcd7d55..b81d2c144f 100644 --- a/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java +++ b/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java @@ -11,9 +11,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import com.google.common.base.Optional; import com.google.common.collect.Lists; +import java.util.Set; import org.hamcrest.CoreMatchers; import org.junit.Test; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -42,6 +46,26 @@ public class JaxBSerializerTest { final NetconfMonitoringService service = new NetconfMonitoringService() { + @Override + public void onSessionUp(final NetconfManagementSession session) { + + } + + @Override + public void onSessionDown(final NetconfManagementSession session) { + + } + + @Override + public void onCapabilitiesAdded(final Set addedCaps) { + + } + + @Override + public void onCapabilitiesRemoved(final Set addedCaps) { + + } + @Override public Sessions getSessions() { return new SessionsBuilder().setSession(Lists.newArrayList(getMockSession(NetconfTcp.class), getMockSession(NetconfSsh.class))).build(); @@ -51,6 +75,16 @@ public class JaxBSerializerTest { public Schemas getSchemas() { return new SchemasBuilder().setSchema(Lists.newArrayList(getMockSchema("id", "v1", Yang.class), getMockSchema("id2", "", Yang.class))).build(); } + + @Override + public String getSchemaForCapability(final String moduleName, final Optional revision) { + return null; + } + + @Override + public Set getCapabilities() { + return null; + } }; final NetconfState model = new NetconfState(service); final String xml = XmlUtil.toString(new JaxBSerializer().toXml(model)).replaceAll("\\s", ""); diff --git a/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java b/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java index 9eab5caff7..a0a0dfcb8f 100644 --- a/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java +++ b/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java @@ -15,8 +15,9 @@ import java.util.Collections; import java.util.Dictionary; import java.util.Hashtable; import java.util.Set; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; import org.opendaylight.controller.netconf.api.util.NetconfConstants; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; @@ -42,16 +43,30 @@ public class Activator implements BundleActivator { final NetconfOperationServiceFactory netconfOperationServiceFactory = new NetconfOperationServiceFactory() { + private final Set capabilities = Collections.singleton(new NotificationsCapability()); + + @Override + public Set getCapabilities() { + return capabilities; + } + + @Override + public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + listener.onCapabilitiesAdded(capabilities); + return new AutoCloseable() { + @Override + public void close() { + listener.onCapabilitiesRemoved(capabilities); + } + }; + } + @Override public NetconfOperationService createService(final String netconfSessionIdForReporting) { return new NetconfOperationService() { private final CreateSubscription createSubscription = new CreateSubscription(netconfSessionIdForReporting, netconfNotificationManager); - @Override - public Set getCapabilities() { - return Collections.singleton(new NotificationsCapability()); - } @Override public Set getNetconfOperations() { @@ -68,7 +83,7 @@ public class Activator implements BundleActivator { } }; - Dictionary properties = new Hashtable<>(); + final Dictionary properties = new Hashtable<>(); properties.put(NetconfConstants.SERVICE_NAME, NetconfConstants.NETCONF_MONITORING); operationaServiceRegistration = context.registerService(NetconfOperationServiceFactory.class, netconfOperationServiceFactory, properties); diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/FakeModuleBuilderCapability.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/FakeModuleBuilderCapability.java index fcb513f016..3aba6f81a3 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/FakeModuleBuilderCapability.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/FakeModuleBuilderCapability.java @@ -12,8 +12,8 @@ import com.google.common.base.Optional; import java.util.Collections; import java.util.Date; import java.util.List; +import org.opendaylight.controller.netconf.api.Capability; import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder; diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java index 68f8796d81..11af568321 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java @@ -12,8 +12,8 @@ import com.google.common.base.Optional; import java.util.Collections; import java.util.Date; import java.util.List; +import org.opendaylight.controller.netconf.api.Capability; import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder; diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java index 30b3076589..bb67af2032 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java @@ -55,19 +55,20 @@ import org.apache.sshd.common.util.ThreadUtils; import org.apache.sshd.server.PasswordAuthenticator; import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider; import org.apache.sshd.server.session.ServerSession; -import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; +import org.opendaylight.controller.netconf.api.Capability; +import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener; +import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; -import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; -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.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator; import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService; import org.opendaylight.controller.netconf.ssh.SshProxyServer; import org.opendaylight.controller.netconf.ssh.SshProxyServerConfiguration; @@ -141,9 +142,15 @@ public class NetconfDeviceSimulator implements Closeable { final SessionIdProvider idProvider = new SessionIdProvider(); + + final AggregatedNetconfOperationServiceFactory aggregatedNetconfOperationServiceFactory = new AggregatedNetconfOperationServiceFactory(); final SimulatedOperationProvider simulatedOperationProvider = new SimulatedOperationProvider(idProvider, capabilities, notificationsFile); - final NetconfMonitoringOperationService monitoringService = new NetconfMonitoringOperationService(new NetconfMonitoringServiceImpl(simulatedOperationProvider)); - simulatedOperationProvider.addService(monitoringService); + + final NetconfMonitoringService monitoringService1 = new NetconfMonitoringServiceImpl(aggregatedNetconfOperationServiceFactory); + final NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory monitoringService = + new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(new NetconfMonitoringOperationService(monitoringService1)); + aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(simulatedOperationProvider); + aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(monitoringService); final DefaultCommitNotificationProducer commitNotifier = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); @@ -152,7 +159,7 @@ public class NetconfDeviceSimulator implements Closeable { : Sets.newHashSet(XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0, XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1); final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( - hashedWheelTimer, simulatedOperationProvider, idProvider, generateConfigsTimeout, commitNotifier, new LoggingMonitoringService(), serverCapabilities); + hashedWheelTimer, aggregatedNetconfOperationServiceFactory, idProvider, generateConfigsTimeout, commitNotifier, monitoringService1, serverCapabilities); final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( serverNegotiatorFactory); @@ -396,65 +403,43 @@ public class NetconfDeviceSimulator implements Closeable { // close Everything } - private static class SimulatedOperationProvider implements NetconfOperationProvider { - private final SessionIdProvider idProvider; - private final Set netconfOperationServices; + private static class SimulatedOperationProvider implements NetconfOperationServiceFactory { + private final Set caps; + private final SimulatedOperationService simulatedOperationService; public SimulatedOperationProvider(final SessionIdProvider idProvider, final Set caps, final Optional notificationsFile) { - this.idProvider = idProvider; - final SimulatedOperationService simulatedOperationService = new SimulatedOperationService(caps, idProvider.getCurrentSessionId(), notificationsFile); - this.netconfOperationServices = Sets.newHashSet(simulatedOperationService); + this.caps = caps; + simulatedOperationService = new SimulatedOperationService(idProvider.getCurrentSessionId(), notificationsFile); } @Override - public NetconfOperationServiceSnapshot openSnapshot(final String sessionIdForReporting) { - return new SimulatedServiceSnapshot(idProvider, netconfOperationServices); + public Set getCapabilities() { + return caps; } - public void addService(final NetconfOperationService monitoringService) { - netconfOperationServices.add(monitoringService); + @Override + public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { + return new AutoCloseable() { + @Override + public void close() throws Exception {} + }; } - private static class SimulatedServiceSnapshot implements NetconfOperationServiceSnapshot { - private final SessionIdProvider idProvider; - private final Set netconfOperationServices; - - public SimulatedServiceSnapshot(final SessionIdProvider idProvider, final Set netconfOperationServices) { - this.idProvider = idProvider; - this.netconfOperationServices = netconfOperationServices; - } - - @Override - public String getNetconfSessionIdForReporting() { - return String.valueOf(idProvider.getCurrentSessionId()); - } - - @Override - public Set getServices() { - return netconfOperationServices; - } - - @Override - public void close() throws Exception {} + @Override + public NetconfOperationService createService(final String netconfSessionIdForReporting) { + return simulatedOperationService; } static class SimulatedOperationService implements NetconfOperationService { - private final Set capabilities; private final long currentSessionId; private final Optional notificationsFile; - public SimulatedOperationService(final Set capabilities, final long currentSessionId, final Optional notificationsFile) { - this.capabilities = capabilities; + public SimulatedOperationService(final long currentSessionId, final Optional notificationsFile) { this.currentSessionId = currentSessionId; this.notificationsFile = notificationsFile; } - @Override - public Set getCapabilities() { - return capabilities; - } - @Override public Set getNetconfOperations() { final DataList storage = new DataList(); @@ -475,16 +460,4 @@ public class NetconfDeviceSimulator implements Closeable { } } - private class LoggingMonitoringService implements SessionMonitoringService { - @Override - public void onSessionUp(final NetconfManagementSession session) { - LOG.debug("Session {} established", session); - } - - @Override - public void onSessionDown(final NetconfManagementSession session) { - LOG.debug("Session {} down", session); - } - } - }