ModuleConfig mapping = moduleConfigs.get(moduleNamespace).get(moduleMappingEntry.getKey());
if (moduleMappingEntry.getValue().isEmpty()) {
- addEmptyModulesCommented(document, modulesElement, moduleNamespace, moduleMappingEntry);
- } else {
- for (ObjectName objectName : moduleMappingEntry.getValue()) {
- modulesElement
- .appendChild(mapping.toXml(objectName, serviceTracker, document, moduleNamespace));
- }
+ continue;
+ }
+
+ for (ObjectName objectName : moduleMappingEntry.getValue()) {
+ modulesElement.appendChild(mapping.toXml(objectName, serviceTracker, document, moduleNamespace));
}
}
return root;
}
- // TODO remove commented modules from output
- private void addEmptyModulesCommented(Document document, Element root, String moduleNamespace,
- Entry<String, Collection<ObjectName>> moduleMappingEntry) {
- Element emptyModule = document.createElement(XmlNetconfConstants.MODULE_KEY);
-
- Element typeElement = XmlUtil.createTextElement(document, XmlNetconfConstants.TYPE_KEY,
- moduleMappingEntry.getKey());
- emptyModule.appendChild(typeElement);
-
- root.appendChild(document.createComment(XmlUtil.toString(emptyModule, false)));
- }
-
// TODO refactor, replace string representing namespace with namespace class
// TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved
// class
public Element toXml(ObjectName rootOn, Set<ObjectName> childRbeOns, Document document, String instanceIndex,
Element parentElement, String namespace) {
- // TODO namespace
Element xml = instanceMapping.toXml(rootOn, null, namespace, document, parentElement);
if (instanceIndex != null) {
public static Config getConfigMapping(ConfigRegistryClient configRegistryClient,
Map<String/* Namespace from yang file */,
Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> mBeanEntries) {
- Map<String, Map<String, ModuleConfig>> factories = transform(configRegistryClient, mBeanEntries);
+ Map<String, Map<String, ModuleConfig>> factories = transformMbeToModuleConfigs(configRegistryClient, mBeanEntries);
return new Config(factories);
}
- // TODO refactor
- private static Map<String/* Namespace from yang file */,
- Map<String /* Name of module entry from yang file */, ModuleConfig>> transform
- (final ConfigRegistryClient configRegistryClient, Map<String/* Namespace from yang file */,
+ public static Map<String/* Namespace from yang file */,
+ Map<String /* Name of module entry from yang file */, ModuleConfig>> transformMbeToModuleConfigs
+ (final ConfigRegistryClient configRegistryClient, Map<String/* Namespace from yang file */,
Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> mBeanEntries) {
- return Maps.transformEntries(mBeanEntries,
- new Maps.EntryTransformer<String, Map<String, ModuleMXBeanEntry>, Map<String, ModuleConfig>>() {
-
- @Override
- public Map<String, ModuleConfig> transformEntry(String arg0, Map<String, ModuleMXBeanEntry> arg1) {
- return Maps.transformEntries(arg1,
- new Maps.EntryTransformer<String, ModuleMXBeanEntry, ModuleConfig>() {
-
- @Override
- public ModuleConfig transformEntry(String key, ModuleMXBeanEntry moduleMXBeanEntry) {
- return new ModuleConfig(key, new InstanceConfig(configRegistryClient, moduleMXBeanEntry
- .getAttributes()), moduleMXBeanEntry.getProvidedServices().values());
- }
- });
- }
- });
+
+ Map<String, Map<String, ModuleConfig>> namespaceToModuleNameToModuleConfig = Maps.newHashMap();
+
+ for (String namespace : mBeanEntries.keySet()) {
+ for (Entry<String, ModuleMXBeanEntry> moduleNameToMbe : mBeanEntries.get(namespace).entrySet()) {
+ String moduleName = moduleNameToMbe.getKey();
+ ModuleMXBeanEntry moduleMXBeanEntry = moduleNameToMbe.getValue();
+
+ ModuleConfig moduleConfig = new ModuleConfig(moduleName, new InstanceConfig(configRegistryClient,
+ moduleMXBeanEntry.getAttributes()), moduleMXBeanEntry
+ .getProvidedServices().values());
+
+ Map<String, ModuleConfig> moduleNameToModuleConfig = namespaceToModuleNameToModuleConfig.get(namespace);
+ if(moduleNameToModuleConfig == null) {
+ moduleNameToModuleConfig = Maps.newHashMap();
+ namespaceToModuleNameToModuleConfig.put(namespace, moduleNameToModuleConfig);
+ }
+
+ moduleNameToModuleConfig.put(moduleName, moduleConfig);
+ }
+ }
+
+ return namespaceToModuleNameToModuleConfig;
}
@Override
import java.util.EnumSet;
import java.util.Set;
-//FIXME: make thread safe
public enum EditStrategyType {
// can be default
merge, replace, none,
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.Runtime;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
-import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.GetConfig;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
final Map<String, Map<String, ModuleRuntime>> moduleRuntimes = createModuleRuntimes(configRegistryClient,
yangStoreSnapshot.getModuleMXBeanEntryMap());
- final Map<String, Map<String, ModuleConfig>> moduleConfigs = GetConfig.transform(configRegistryClient,
- yangStoreSnapshot.getModuleMXBeanEntryMap());
+ final Map<String, Map<String, ModuleConfig>> moduleConfigs = EditConfig.transformMbeToModuleConfigs(
+ configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
package org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig;
import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
-import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
final Set<ObjectName> instances = Datastore.getInstanceQueryStrategy(source, this.transactionProvider)
.queryInstances(configRegistryClient);
- final Config configMapping = new Config(transform(configRegistryClient,
+ final Config configMapping = new Config(EditConfig.transformMbeToModuleConfigs(configRegistryClient,
yangStoreSnapshot.getModuleMXBeanEntryMap()));
return dataElement;
}
- // TODO refactor ... duplicate code
- public static Map<String, Map<String, ModuleConfig>> transform(final ConfigRegistryClient configRegistryClient,
- Map<String, Map<String, ModuleMXBeanEntry>> mBeanEntries) {
- return Maps.transformEntries(mBeanEntries,
- new Maps.EntryTransformer<String, Map<String, ModuleMXBeanEntry>, Map<String, ModuleConfig>>() {
-
- @Override
- public Map<String, ModuleConfig> transformEntry(String arg0, Map<String, ModuleMXBeanEntry> arg1) {
- return Maps.transformEntries(arg1,
- new Maps.EntryTransformer<String, ModuleMXBeanEntry, ModuleConfig>() {
-
- @Override
- public ModuleConfig transformEntry(String key, ModuleMXBeanEntry value) {
- return new ModuleConfig(key, new InstanceConfig(configRegistryClient, value
- .getAttributes()), value.getProvidedServices().values());
- }
- });
- }
- });
- }
-
@Override
protected String getOperationName() {
return GET_CONFIG;
if (contextInstanceElement.isPresent() == false)
return HandlingPriority.CANNOT_HANDLE;
- // FIXME update xpath to instance to conform to config-api yang
final RuntimeRpcElementResolved id = RuntimeRpcElementResolved.fromXpath(contextInstanceElement.get()
.getTextContent(), netconfOperationName, netconfOperationNamespace);
package org.opendaylight.controller.netconf.confignetconfconnector.util;
import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.yang.store.api.YangStoreException;
-import org.opendaylight.controller.config.yang.store.api.YangStoreService;
-import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+ " should be " + clazz + " of " + value);
}
- // TODO: add message and proper error types
- public static YangStoreSnapshot getYangStore(final YangStoreService yangStoreService)
- throws NetconfDocumentedException {
- try {
- return yangStoreService.getYangStoreSnapshot();
- } catch (final YangStoreException e) {
- throw new NetconfDocumentedException("TODO", e, ErrorType.application, ErrorTag.bad_attribute,
- ErrorSeverity.error);
- }
- }
-
}
package org.opendaylight.controller.netconf.persist.impl;
+import org.opendaylight.controller.config.persist.api.Persister;
import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
import org.opendaylight.controller.netconf.api.jmx.DefaultCommitOperationMXBean;
import org.opendaylight.controller.netconf.api.jmx.NetconfJMXNotification;
private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterNotificationHandler.class);
private final MBeanServerConnection mBeanServerConnection;
private final NetconfClient netconfClient;
- private final PersisterAggregator persisterAggregator;
+ private final Persister persisterAggregator;
private final Pattern ignoredMissingCapabilityRegex;
public ConfigPersisterNotificationHandler(MBeanServerConnection mBeanServerConnection, NetconfClient netconfClient,
- PersisterAggregator persisterAggregator, Pattern ignoredMissingCapabilityRegex) {
+ Persister persisterAggregator, Pattern ignoredMissingCapabilityRegex) {
this.mBeanServerConnection = mBeanServerConnection;
this.netconfClient = netconfClient;
this.persisterAggregator = persisterAggregator;
if (notification instanceof CommitJMXNotification) {
try {
handleAfterCommitNotification((CommitJMXNotification) notification);
- } catch (Exception e) {
- // TODO: notificationBroadcast support logs only DEBUG
+ } catch (Throwable e) {
+ // log exceptions from notification Handler here since
+ // notificationBroadcastSupport logs only DEBUG level
logger.warn("Exception occured during notification handling: ", e);
throw e;
}
return true;
}
-
- // TODO: check if closing in correct order
public static void closeClientAndDispatcher(NetconfClient client) {
NetconfClientDispatcher dispatcher = client.getNetconfClientDispatcher();
Exception fromClient = null;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
import org.opendaylight.controller.netconf.mapping.api.Capability;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.Map;
private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
private final Set<String> capabilityURIs;
+ private static final Logger logger = LoggerFactory.getLogger(DefaultCommitNotificationProducer.class);
+
public CapabilityProviderImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
Map<String, Capability> urisToCapabilitiesInternalMap = getCapabilitiesInternal(netconfOperationServiceSnapshot);
final Set<Capability> caps = netconfOperationService.getCapabilities();
for (Capability cap : caps) {
- // TODO check for duplicates ?
+
+ if(capabilityMap.containsKey(cap.getCapabilityUri())) {
+ logger.debug("Duplicate capability {} from service {}", cap.getCapabilityUri(), netconfOperationService);
+ }
+
capabilityMap.put(cap.getCapabilityUri(), cap);
}
}
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler;
import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
import org.opendaylight.protocol.framework.AbstractDispatcher;
+import java.net.InetSocketAddress;
+
public class NetconfServerDispatcher extends AbstractDispatcher<NetconfSession, NetconfServerSessionListener> {
private final ServerChannelInitializer initializer;
this.initializer = serverChannelInitializer;
}
- // TODO test create server with same address twice
public ChannelFuture createServer(InetSocketAddress address) {
return super.createServer(address, new PipelineInitializer<NetconfSession>() {
package org.opendaylight.controller.netconf.impl;
+import com.google.common.base.Preconditions;
import io.netty.channel.Channel;
import io.netty.util.Timer;
import io.netty.util.concurrent.Promise;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
+import java.io.InputStream;
public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorFactory {
+ public static final String SERVER_HELLO_XML_LOCATION = "/server_hello.xml";
+
private final Timer timer;
private static final Document helloMessageTemplate = loadHelloMessageTemplate();
}
private static Document loadHelloMessageTemplate() {
- return NetconfUtil.createMessage(
- NetconfServerSessionNegotiatorFactory.class.getResourceAsStream("/server_hello.xml")).getDocument();
+ InputStream resourceAsStream = NetconfServerSessionNegotiatorFactory.class
+ .getResourceAsStream(SERVER_HELLO_XML_LOCATION);
+ Preconditions.checkNotNull(resourceAsStream, "Unable to load server hello message blueprint from %s",
+ SERVER_HELLO_XML_LOCATION);
+ return NetconfUtil.createMessage(resourceAsStream).getDocument();
}
@Override
@Override
public Schemas getSchemas() {
// FIXME, session ID
+ // capabilities should be split from operations (it will allow to move getSchema operation to monitoring module)
return transformSchemas(factoriesListener.getSnapshot(0));
}
for (NetconfOperationService netconfOperationService : snapshot.getServices()) {
// TODO check for duplicates ? move capability merging to snapshot
+ // Split capabilities from operations first and delete this duplicate code
caps.addAll(netconfOperationService.getCapabilities());
}
monitoringLocations.add(new Schema.Location(Schema.Location.Enumeration.NETCONF));
for (String location : locations) {
- // TODO how to create enumerration from string location ?
- // monitoringLocations.add(new Schema.Location(Schema.Location.Enumeration.valueOf(location)));
+ monitoringLocations.add(new Schema.Location(new Uri(location)));
}
return monitoringLocations;
private NetconfOperationExecution getNetconfOperationWithHighestPriority(
Document message, NetconfSession session) {
- // TODO test
TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
message, session);
package org.opendaylight.controller.netconf.impl.util;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
-// TODO purge nulls
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
public class NetconfUtil {
private static final Logger logger = LoggerFactory.getLogger(NetconfUtil.class);
public static NetconfMessage createMessage(final File f) {
+ Preconditions.checkNotNull(f, "File parameter was null");
try {
return createMessage(new FileInputStream(f));
} catch (final FileNotFoundException e) {
}
public static NetconfMessage createMessage(final InputStream is) {
+ Preconditions.checkNotNull(is, "InputStream parameter was null");
Document doc = null;
try {
doc = XmlUtil.readXmlToDocument(is);
public class NetconfDispatcherImplTest {
private EventLoopGroup nettyGroup;
+ private NetconfServerDispatcher dispatch;
+ private DefaultCommitNotificationProducer commitNot;
@Before
public void setUp() throws Exception {
nettyGroup = new NioEventLoopGroup();
- }
-
- @After
- public void tearDown() throws Exception {
- nettyGroup.shutdownGracefully();
- }
- @Test
- public void test() throws Exception {
-
- DefaultCommitNotificationProducer commitNot = new DefaultCommitNotificationProducer(
+ commitNot = new DefaultCommitNotificationProducer(
ManagementFactory.getPlatformMBeanServer());
NetconfOperationServiceFactoryListener factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
factoriesListener, commitNot, idProvider, null);
NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(serverNegotiatorFactory, listenerFactory);
-
- NetconfServerDispatcher dispatch = new NetconfServerDispatcher(
+ dispatch = new NetconfServerDispatcher(
serverChannelInitializer, nettyGroup, nettyGroup);
+ }
+ @After
+ public void tearDown() throws Exception {
+ commitNot.close();
+ nettyGroup.shutdownGracefully();
+ }
+
+ @Test
+ public void test() throws Exception {
InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8333);
ChannelFuture s = dispatch.createServer(addr);
-
- commitNot.close();
+ s.get();
}
}
--- /dev/null
+/*
+ * 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.it;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
+import org.opendaylight.controller.netconf.client.NetconfClient;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
+import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
+import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
+import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.Capability;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
+import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
+import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class NetconfConfigPersisterITTest extends AbstractConfigTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(NetconfConfigPersisterITTest.class);
+
+ private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
+
+ private EventLoopGroup nettyThreadgroup;
+
+ private NetconfClientDispatcher clientDispatcher;
+
+ @Before
+ public void setUp() throws Exception {
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray(
+ new ModuleFactory[0])));
+
+ NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getFactoriesListener());
+
+ NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+ factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
+ factoriesListener
+ .onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
+ new NetconfMonitoringOperationService(monitoringService)));
+
+ nettyThreadgroup = new NioEventLoopGroup();
+
+ NetconfServerDispatcher dispatch = createDispatcher(factoriesListener);
+ ChannelFuture s = dispatch.createServer(tcpAddress);
+ s.await();
+
+ clientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup);
+ }
+
+ private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
+ final Collection<InputStream> yangDependencies = NetconfITTest.getBasicYangs();
+ return new HardcodedYangStoreService(yangDependencies);
+ }
+
+ private NetconfServerDispatcher createDispatcher(
+ NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+ SessionIdProvider idProvider = new SessionIdProvider();
+ NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+ new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
+
+ NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
+ factoriesListener, new DefaultCommitNotificationProducer(platformMBeanServer), idProvider, mockSessionMonitoringService());
+
+ NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+ serverNegotiatorFactory, listenerFactory);
+ return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
+ }
+
+ private SessionMonitoringService mockSessionMonitoringService() {
+ SessionMonitoringService mockedSessionMonitor = mock(SessionMonitoringService.class);
+ doNothing().when(mockedSessionMonitor).onSessionUp(any(NetconfManagementSession.class));
+ doNothing().when(mockedSessionMonitor).onSessionDown(any(NetconfManagementSession.class));
+ return mockedSessionMonitor;
+ }
+
+ @Test
+ public void testNetconfCommitNotifications() throws Exception {
+
+ VerifyingNotificationListener notificationVerifier = createCommitNotificationListener();
+ VerifyingPersister mockedAggregator = mockAggregator();
+
+ try (NetconfClient persisterClient = new NetconfClient("persister", tcpAddress, 4000, clientDispatcher)) {
+ ConfigPersisterNotificationHandler configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(
+ platformMBeanServer, persisterClient, mockedAggregator,
+ Pattern.compile(""));
+ configPersisterNotificationHandler.init();
+
+ try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, clientDispatcher)) {
+ NetconfMessage response = netconfClient.sendMessage(loadGetConfigMessage());
+ assertResponse(response, "<modules");
+ assertResponse(response, "<services");
+ response = netconfClient.sendMessage(loadCommitMessage());
+ assertResponse(response, "ok");
+
+ response = netconfClient.sendMessage(loadEditConfigMessage());
+ assertResponse(response, "ok");
+ response = netconfClient.sendMessage(loadCommitMessage());
+ assertResponse(response, "ok");
+ }
+ }
+
+ notificationVerifier.assertNotificationCount(2);
+ notificationVerifier.assertNotificationContent(0, 0, 0, 9);
+ notificationVerifier.assertNotificationContent(1, 4, 4, 9);
+
+ mockedAggregator.assertSnapshotCount(2);
+ // Capabilities are stripped for persister
+ mockedAggregator.assertSnapshotContent(0, 0, 0, 1);
+ mockedAggregator.assertSnapshotContent(1, 4, 4, 3);
+ }
+
+ private VerifyingPersister mockAggregator() throws IOException {
+ return new VerifyingPersister();
+ }
+
+ private VerifyingNotificationListener createCommitNotificationListener() throws InstanceNotFoundException {
+ VerifyingNotificationListener listener = new VerifyingNotificationListener();
+ platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.objectName, listener, null, null);
+ return listener;
+ }
+
+ private void assertResponse(NetconfMessage response, String content) {
+ Assert.assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString(content));
+ }
+
+ private NetconfMessage loadGetConfigMessage() throws Exception {
+ return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
+ }
+
+ private NetconfMessage loadEditConfigMessage() throws Exception {
+ return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig.xml");
+ }
+
+ private NetconfMessage loadCommitMessage() throws Exception {
+ return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
+ }
+
+
+ public NetconfOperationServiceFactoryListener getFactoriesListener() {
+ NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class);
+ NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class);
+ NetconfOperationService service = mock(NetconfOperationService.class);
+ Set<Capability> caps = Sets.newHashSet();
+ doReturn(caps).when(service).getCapabilities();
+ Set<NetconfOperationService> services = Sets.newHashSet(service);
+ doReturn(services).when(snap).getServices();
+ doReturn(snap).when(factoriesListener).getSnapshot(anyLong());
+
+ return factoriesListener;
+ }
+
+ private static class VerifyingNotificationListener implements NotificationListener {
+ public List<Notification> notifications = Lists.newArrayList();
+
+ @Override
+ public void handleNotification(Notification notification, Object handback) {
+ this.notifications.add(notification);
+ }
+
+ void assertNotificationCount(Object size) {
+ assertEquals(size, notifications.size());
+ }
+
+ void assertNotificationContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize) {
+ Notification notification = notifications.get(notificationIndex);
+ assertEquals(CommitJMXNotification.class, notification.getClass());
+ int capsSize = ((CommitJMXNotification) notification).getCapabilities().size();
+ assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
+ Element configSnapshot = ((CommitJMXNotification) notification).getConfigSnapshot();
+ int modulesSize = configSnapshot.getElementsByTagName("module").getLength();
+ assertEquals("Expected modules count", expectedModulesSize, modulesSize);
+ int servicesSize = configSnapshot.getElementsByTagName("instance").getLength();
+ assertEquals("Expected services count", expectedServicesSize, servicesSize);
+ }
+ }
+
+ private static class VerifyingPersister implements Persister {
+
+ public List<ConfigSnapshotHolder> snapshots = Lists.newArrayList();
+ private Persister mockedPersister;
+
+ public VerifyingPersister() throws IOException {
+ Persister mockedAggregator = mock(Persister.class);
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
+ snapshots.add(configSnapshot);
+ return null;
+ }
+ }).when(mockedAggregator).persistConfig(any(ConfigSnapshotHolder.class));
+
+ this.mockedPersister = mockedAggregator;
+ }
+
+ void assertSnapshotCount(Object size) {
+ assertEquals(size, snapshots.size());
+ }
+
+ void assertSnapshotContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize) {
+ ConfigSnapshotHolder snapshot = snapshots.get(notificationIndex);
+ int capsSize = snapshot.getCapabilities().size();
+ assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
+ String configSnapshot = snapshot.getConfigSnapshot();
+ int modulesSize = StringUtils.countMatches(configSnapshot, "<module>");
+ assertEquals("Expected modules count", expectedModulesSize, modulesSize);
+ int servicesSize = StringUtils.countMatches(configSnapshot, "<instance>");
+ assertEquals("Expected services count", expectedServicesSize, servicesSize);
+ }
+
+ @Override
+ public void persistConfig(ConfigSnapshotHolder configSnapshotHolder) throws IOException {
+ mockedPersister.persistConfig(configSnapshotHolder);
+ }
+
+ @Override
+ public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
+ return mockedPersister.loadLastConfigs();
+ }
+
+ @Override
+ public void close() {
+ mockedPersister.close();
+ }
+ }
+}
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
+
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
import static java.util.Collections.emptyList;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
}
}
-
- //TODO: test persister actually
- @Ignore
- @Test(timeout = 10000)
- public void testPersister() throws Exception {
-// Persister persister = mock(Persister.class);
-// doReturn("mockPersister").when(persister).toString();
-// doReturn(Collections.emptyList()).when(persister).loadLastConfigs();
-// ConfigPersisterNotificationHandler h =
-// new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer(),
-// Pattern.compile(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX));
-// h.init();
- }
-
@Ignore
@Test
public void waitingTest() throws Exception {
*/
package org.opendaylight.controller.netconf.it;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
import junit.framework.Assert;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.matchers.JUnitMatchers;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
public class NetconfMonitoringITTest extends AbstractConfigTest {
return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
}
- public NetconfOperationServiceFactoryListener getFactoriesListener() {
+ public static NetconfOperationServiceFactoryListener getFactoriesListener() {
NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class);
NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class);
NetconfOperationService service = mock(NetconfOperationService.class);
return Optional.of(priority).or(Optional.<Integer> absent());
}
- // TODO test
-
@Override
public int compareTo(HandlingPriority o) {
if (this == o)
public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionPreferences, S extends NetconfSession>
extends AbstractSessionNegotiator<NetconfMessage, S> {
- // TODO what time ?
+ // TODO Adjust wait time for negotiation, now is 1 minute ?
private static final long INITIAL_HOLDTIMER = 1;
private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSessionNegotiator.class);
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" id="a" message-id="101" xmlnx="a:b:c:d">
<data>
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <!--<module>
- <type>impl</type>
- </module>
- -->
- <!--<module>
- <type>impl-dep</type>
- </module>
- -->
- <!--<module>
- <type>impl-netconf</type>
- </module>
- -->
- </modules>
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config"/>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config"/>
</data>
</rpc-reply>