From: Tomas Cere Date: Mon, 11 Apr 2016 11:21:02 +0000 (+0000) Subject: Merge "Bug 3866: Support for Restconf HTTP Patch" X-Git-Tag: release/boron~150 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=c0488b3e5a8d1bbe2894eda5eb1254f6ced347a4;hp=1b201765421dfa26a0a58b5a5b6e42ba4f3cf860;p=netconf.git Merge "Bug 3866: Support for Restconf HTTP Patch" --- diff --git a/features/netconf-connector/pom.xml b/features/netconf-connector/pom.xml index 9190706595..07ecb6137a 100644 --- a/features/netconf-connector/pom.xml +++ b/features/netconf-connector/pom.xml @@ -21,7 +21,6 @@ jar - 0.4.0-SNAPSHOT 1.7.0-SNAPSHOT 1.4.0-SNAPSHOT 0.5.0-SNAPSHOT @@ -81,13 +80,6 @@ features xml - - org.opendaylight.aaa - features-aaa - ${aaa.version} - features - xml - ${project.groupId} sal-netconf-connector diff --git a/features/netconf/pom.xml b/features/netconf/pom.xml index c8dbc730d4..c82dc1c23a 100644 --- a/features/netconf/pom.xml +++ b/features/netconf/pom.xml @@ -117,12 +117,6 @@ features xml - - org.opendaylight.aaa - features-aaa - features - xml - org.opendaylight.aaa features-aaa-shiro diff --git a/features/netconf/src/main/features/features.xml b/features/netconf/src/main/features/features.xml index e547e7572f..82920bcba1 100644 --- a/features/netconf/src/main/features/features.xml +++ b/features/netconf/src/main/features/features.xml @@ -8,7 +8,7 @@ mvn:org.opendaylight.controller/features-config/{{VERSION}}/xml/features mvn:org.opendaylight.controller/features-config-persister/{{VERSION}}/xml/features mvn:org.opendaylight.controller/features-config-netty/{{VERSION}}/xml/features - mvn:org.opendaylight.aaa/features-aaa/${aaa.version}/xml/features + mvn:org.opendaylight.aaa/features-aaa-shiro/${aaa.version}/xml/features odl-netconf-api @@ -142,7 +142,7 @@ version='${project.version}'> odl-config-api mvn:org.opendaylight.netconf/netconf-auth/{{VERSION}} - odl-aaa-authn + odl-aaa-shiro mvn:org.opendaylight.netconf/aaa-authn-odl-plugin/{{VERSION}} @@ -151,7 +151,7 @@ version='${project.version}'> odl-config-api mvn:org.opendaylight.netconf/netconf-auth/{{VERSION}} - odl-aaa-authn-no-cluster + odl-aaa-shiro mvn:org.opendaylight.netconf/aaa-authn-odl-plugin/{{VERSION}} diff --git a/netconf/mdsal-netconf-notification/src/main/java/org/opendaylight/netconf/mdsal/notification/NetconfNotificationOperationService.java b/netconf/mdsal-netconf-notification/src/main/java/org/opendaylight/netconf/mdsal/notification/NetconfNotificationOperationService.java index 94678c9d55..9824e1e57b 100644 --- a/netconf/mdsal-netconf-notification/src/main/java/org/opendaylight/netconf/mdsal/notification/NetconfNotificationOperationService.java +++ b/netconf/mdsal-netconf-notification/src/main/java/org/opendaylight/netconf/mdsal/notification/NetconfNotificationOperationService.java @@ -30,6 +30,14 @@ public class NetconfNotificationOperationService implements NetconfOperationServ @Override public void close() { - + for (NetconfOperation netconfOperation : netconfOperations) { + if (netconfOperation instanceof AutoCloseable) { + try { + ((AutoCloseable) netconfOperation).close(); + } catch (Exception e) { + throw new IllegalStateException("Exception while closing " + netconfOperation, e); + } + } + } } } diff --git a/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/xml/XmlNetconfConstants.java b/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/xml/XmlNetconfConstants.java index 7cac46a013..33bbef5cd5 100644 --- a/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/xml/XmlNetconfConstants.java +++ b/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/xml/XmlNetconfConstants.java @@ -24,6 +24,7 @@ public final class XmlNetconfConstants { public static final String SOURCE_KEY = "source"; public static final String RPC_KEY = "rpc"; public static final String NOTIFICATION_ELEMENT_NAME = "notification"; + public static final String EVENT_TIME = "eventTime"; public static final String MESSAGE_ID = "message-id"; public static final String SESSION_ID = "session-id"; @@ -35,6 +36,7 @@ public final class XmlNetconfConstants { public static final String URN_IETF_PARAMS_NETCONF_BASE_1_0 = "urn:ietf:params:netconf:base:1.0"; public static final String URN_IETF_PARAMS_NETCONF_BASE_1_1 = "urn:ietf:params:netconf:base:1.1"; public static final String URN_IETF_PARAMS_XML_NS_NETCONF_EXI_1_0 = "urn:ietf:params:xml:ns:netconf:exi:1.0"; + public static final String URN_IETF_PARAMS_NETCONF_CAPABILITY_NOTIFICATION_1_0 = "urn:ietf:params:netconf:capability:notification:1.0"; public static final String URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0 = "urn:ietf:params:netconf:capability:exi:1.0"; public static final String URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"; diff --git a/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/TestingNetconfClient.java b/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/TestingNetconfClient.java index 131bea9671..dabe11a3ed 100644 --- a/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/TestingNetconfClient.java +++ b/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/TestingNetconfClient.java @@ -25,12 +25,12 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler; -import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPassword; import org.opendaylight.netconf.api.NetconfMessage; import org.opendaylight.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.netconf.client.conf.NetconfClientConfiguration.NetconfClientProtocol; import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder; +import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPassword; import org.opendaylight.protocol.framework.NeverReconnectStrategy; @@ -47,21 +47,21 @@ public class TestingNetconfClient implements Closeable { private final long sessionId; public TestingNetconfClient(String clientLabel, - NetconfClientDispatcher netconfClientDispatcher, final NetconfClientConfiguration config) throws InterruptedException { + NetconfClientDispatcher netconfClientDispatcher, final NetconfClientConfiguration config) throws InterruptedException { this.label = clientLabel; sessionListener = config.getSessionListener(); Future clientFuture = netconfClientDispatcher.createClient(config); - clientSession = get(clientFuture);//TODO: make static + clientSession = get(clientFuture); this.sessionId = clientSession.getSessionId(); } - private NetconfClientSession get(Future clientFuture) throws InterruptedException { + private static NetconfClientSession get(Future clientFuture) throws InterruptedException { try { return clientFuture.get(); } catch (CancellationException e) { - throw new RuntimeException("Cancelling " + this, e); + throw new RuntimeException("Cancelling " + TestingNetconfClient.class.getSimpleName(), e); } catch (ExecutionException e) { - throw new IllegalStateException("Unable to create " + this, e); + throw new IllegalStateException("Unable to create " + TestingNetconfClient.class.getSimpleName(), e); } } diff --git a/netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/NetconfServerSessionListener.java b/netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/NetconfServerSessionListener.java index a1a16f426c..ca61311cdc 100644 --- a/netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/NetconfServerSessionListener.java +++ b/netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/NetconfServerSessionListener.java @@ -20,6 +20,7 @@ import org.opendaylight.netconf.api.NetconfTerminationReason; import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.netconf.impl.osgi.NetconfOperationRouter; +import org.opendaylight.netconf.util.messages.SubtreeFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -112,7 +113,7 @@ public class NetconfServerSessionListener implements NetconfSessionListener sessions = new HashSet<>(); private final NetconfOperationServiceFactory netconfOperationProvider; private final Map capabilities = new HashMap<>(); + private final Map> mappedModulesToRevisionToSchema = Maps.newHashMap(); private final Set listeners = Sets.newHashSet(); private volatile BaseNotificationPublisherRegistration notificationPublisher; @@ -117,33 +118,9 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, A @Override public synchronized 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)); + + "available modules : %s", moduleName, Collections2.transform(capabilities.values(), CAPABILITY_TO_URI)); if (revision.isPresent()) { String schema = revisionMapRequest.get(revision.get()); @@ -161,6 +138,42 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, A } } + private synchronized void updateCapabilityToSchemaMap(final Set added, final Set removed) { + for (final Capability cap : added) { + if (!isValidModuleCapability(cap)){ + continue; + } + + final String currentModuleName = cap.getModuleName().get(); + Map revisionMap = mappedModulesToRevisionToSchema.get(currentModuleName); + if (revisionMap == null) { + revisionMap = Maps.newHashMap(); + mappedModulesToRevisionToSchema.put(currentModuleName, revisionMap); + } + + final String currentRevision = cap.getRevision().get(); + revisionMap.put(currentRevision, cap.getCapabilitySchema().get()); + } + for (final Capability cap : removed) { + if (!isValidModuleCapability(cap)){ + continue; + } + final Map revisionMap = mappedModulesToRevisionToSchema.get(cap.getModuleName().get()); + if (revisionMap != null) { + revisionMap.remove(cap.getRevision().get()); + if (revisionMap.isEmpty()) { + mappedModulesToRevisionToSchema.remove(cap.getModuleName().get()); + } + } + } + } + + private boolean isValidModuleCapability(Capability cap) { + return cap.getModuleName().isPresent() + && cap.getRevision().isPresent() + && cap.getCapabilitySchema().isPresent(); + } + @Override public synchronized Capabilities getCapabilities() { return new CapabilitiesBuilder().setCapability(Lists.newArrayList(capabilities.keySet())).build(); @@ -250,6 +263,7 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, A public void onCapabilitiesChanged(Set added, Set removed) { onCapabilitiesAdded(added); onCapabilitiesRemoved(removed); + updateCapabilityToSchemaMap(added, removed); notifyListeners(); // publish notification to notification collector about changed capabilities diff --git a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/MessageHeaderTest.java b/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/MessageHeaderTest.java deleted file mode 100644 index 40ab00c42e..0000000000 --- a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/MessageHeaderTest.java +++ /dev/null @@ -1,32 +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.netconf.impl; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.opendaylight.netconf.util.messages.NetconfMessageHeader; - -@Deprecated -public class MessageHeaderTest { - @Test - public void testFromBytes() { - final byte[] raw = new byte[] { (byte) 0x0a, (byte) 0x23, (byte) 0x35, (byte) 0x38, (byte) 0x0a }; - NetconfMessageHeader header = NetconfMessageHeader.fromBytes(raw); - assertEquals(58, header.getLength()); - } - - @Test - public void testToBytes() { - NetconfMessageHeader header = new NetconfMessageHeader(123); - assertArrayEquals(new byte[] { (byte) 0x0a, (byte) 0x23, (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x0a }, - header.toBytes()); - } -} diff --git a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/MessageParserTest.java b/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/MessageParserTest.java index df34c45c5f..562d4a4ba9 100644 --- a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/MessageParserTest.java +++ b/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/MessageParserTest.java @@ -15,12 +15,15 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import com.google.common.base.Charsets; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.embedded.EmbeddedChannel; +import java.nio.ByteBuffer; import java.util.Queue; import org.junit.Before; import org.junit.Test; +import org.opendaylight.netconf.api.NetconfMessage; import org.opendaylight.netconf.nettyutil.handler.ChunkedFramingMechanismEncoder; import org.opendaylight.netconf.nettyutil.handler.FramingMechanismHandlerFactory; import org.opendaylight.netconf.nettyutil.handler.NetconfChunkAggregator; @@ -29,9 +32,7 @@ import org.opendaylight.netconf.nettyutil.handler.NetconfMessageToXMLEncoder; import org.opendaylight.netconf.nettyutil.handler.NetconfXMLToMessageDecoder; import org.opendaylight.netconf.util.messages.FramingMechanism; import org.opendaylight.netconf.util.messages.NetconfMessageConstants; -import org.opendaylight.netconf.util.messages.NetconfMessageHeader; import org.opendaylight.netconf.util.test.XmlFileLoader; -import org.opendaylight.netconf.api.NetconfMessage; public class MessageParserTest { @@ -78,8 +79,7 @@ public class MessageParserTest { byte[] header = new byte[String.valueOf(exptHeaderLength).length() + NetconfMessageConstants.MIN_HEADER_LENGTH - 1]; recievedOutbound.getBytes(0, header); - NetconfMessageHeader messageHeader = NetconfMessageHeader.fromBytes(header); - assertEquals(exptHeaderLength, messageHeader.getLength()); + assertEquals(exptHeaderLength, getHeaderLength(header)); testChunkChannel.writeInbound(recievedOutbound); } @@ -108,4 +108,10 @@ public class MessageParserTest { assertNotNull(receivedMessage); assertXMLEqual(this.msg.getDocument(), receivedMessage.getDocument()); } + + private static long getHeaderLength(byte[] bytes) { + byte[] HEADER_START = new byte[] { (byte) 0x0a, (byte) 0x23 }; + return Long.parseLong(Charsets.US_ASCII.decode( + ByteBuffer.wrap(bytes, HEADER_START.length, bytes.length - HEADER_START.length - 1)).toString()); + } } diff --git a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/osgi/NetconfMonitoringServiceImplTest.java b/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/osgi/NetconfMonitoringServiceImplTest.java index 3181030fee..6f1c91ceeb 100644 --- a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/osgi/NetconfMonitoringServiceImplTest.java +++ b/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/osgi/NetconfMonitoringServiceImplTest.java @@ -13,7 +13,7 @@ import static org.mockito.Mockito.doReturn; import com.google.common.base.Optional; import java.net.URI; import java.util.ArrayList; -import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -21,6 +21,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -39,33 +40,41 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.mon import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.SessionBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; import org.opendaylight.yangtools.yang.model.api.Module; public class NetconfMonitoringServiceImplTest { private static final String TEST_MODULE_CONTENT = "content"; + private static final String TEST_MODULE_CONTENT2 = "content2"; private static final String TEST_MODULE_REV = "1970-01-01"; + private static final String TEST_MODULE_REV2 = "1970-01-02"; private static final Uri TEST_MODULE_NAMESPACE = new Uri("testModuleNamespace"); private static final String TEST_MODULE_NAME = "testModule"; - private static final Date TEST_MODULE_DATE; + private static Date TEST_MODULE_DATE; + private static Date TEST_MODULE_DATE2; - static { - Calendar calendar = Calendar.getInstance(); - calendar.set(1970, Calendar.JANUARY, 1); - TEST_MODULE_DATE = calendar.getTime(); - } + private YangModuleCapability moduleCapability1; + private YangModuleCapability moduleCapability2; private final Set CAPABILITIES = new HashSet<>(); private NetconfMonitoringServiceImpl monitoringService; - @Mock private Module moduleMock; @Mock + private Module moduleMock2; + @Mock private NetconfOperationServiceFactory operationServiceFactoryMock; @Mock private NetconfManagementSession sessionMock; + @BeforeClass + public static void suiteSetUp() throws Exception { + TEST_MODULE_DATE = SimpleDateFormatUtil.getRevisionFormat().parse(TEST_MODULE_REV); + TEST_MODULE_DATE2= SimpleDateFormatUtil.getRevisionFormat().parse(TEST_MODULE_REV2); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -75,14 +84,20 @@ public class NetconfMonitoringServiceImplTest { doReturn(new URI(TEST_MODULE_NAMESPACE.getValue())).when(moduleMock).getNamespace(); doReturn(TEST_MODULE_NAME).when(moduleMock).getName(); doReturn(TEST_MODULE_DATE).when(moduleMock).getRevision(); - doReturn(TEST_MODULE_NAME).when(moduleMock).getName(); + moduleCapability1 = new YangModuleCapability(moduleMock, TEST_MODULE_CONTENT); + + CAPABILITIES.add(moduleCapability1); + + doReturn(new URI(TEST_MODULE_NAMESPACE.getValue())).when(moduleMock2).getNamespace(); + doReturn(TEST_MODULE_NAME).when(moduleMock2).getName(); + doReturn(TEST_MODULE_DATE2).when(moduleMock2).getRevision(); + moduleCapability2 = new YangModuleCapability(moduleMock2, TEST_MODULE_CONTENT2); - CAPABILITIES.add(new YangModuleCapability(moduleMock, TEST_MODULE_CONTENT)); doReturn(CAPABILITIES).when(operationServiceFactoryMock).getCapabilities(); doReturn(null).when(operationServiceFactoryMock).registerCapabilityListener(any(NetconfMonitoringServiceImpl.class)); monitoringService = new NetconfMonitoringServiceImpl(operationServiceFactoryMock); - monitoringService.onCapabilitiesChanged(CAPABILITIES, new HashSet()); + monitoringService.onCapabilitiesChanged(CAPABILITIES, Collections.emptySet()); doReturn(new SessionBuilder().build()).when(sessionMock).toManagementSession(); } @@ -115,9 +130,17 @@ public class NetconfMonitoringServiceImplTest { @Test public void testGetSchemaForCapability() throws Exception { - String schema = monitoringService.getSchemaForCapability(TEST_MODULE_NAME, Optional.of(TEST_MODULE_REV)); + //test multiple revisions of the same capability + monitoringService.onCapabilitiesChanged(Collections.singleton(moduleCapability2), Collections.emptySet()); + final String schema = monitoringService.getSchemaForCapability(TEST_MODULE_NAME, Optional.of(TEST_MODULE_REV)); Assert.assertEquals(TEST_MODULE_CONTENT, schema); - + final String schema2 = monitoringService.getSchemaForCapability(TEST_MODULE_NAME, Optional.of(TEST_MODULE_REV2)); + Assert.assertEquals(TEST_MODULE_CONTENT2, schema2); + //remove one revision + monitoringService.onCapabilitiesChanged(Collections.emptySet(), Collections.singleton(moduleCapability1)); + //only one revision present + final String schema3 = monitoringService.getSchemaForCapability(TEST_MODULE_NAME, Optional.absent()); + Assert.assertEquals(TEST_MODULE_CONTENT2, schema3); } @Test diff --git a/netconf/netconf-notifications-api/src/main/java/org/opendaylight/netconf/notifications/NetconfNotification.java b/netconf/netconf-notifications-api/src/main/java/org/opendaylight/netconf/notifications/NetconfNotification.java index 7111a6cbb3..852682a15e 100644 --- a/netconf/netconf-notifications-api/src/main/java/org/opendaylight/netconf/notifications/NetconfNotification.java +++ b/netconf/netconf-notifications-api/src/main/java/org/opendaylight/netconf/notifications/NetconfNotification.java @@ -34,6 +34,8 @@ public final class NetconfNotification extends NetconfMessage { */ public static final Date UNKNOWN_EVENT_TIME = new Date(0); + private final Date eventTime; + /** * Create new notification and capture the timestamp in the constructor */ @@ -46,6 +48,14 @@ public final class NetconfNotification extends NetconfMessage { */ public NetconfNotification(final Document notificationContent, final Date eventTime) { super(wrapNotification(notificationContent, eventTime)); + this.eventTime = eventTime; + } + + /** + * @return notification event time + */ + public Date getEventTime() { + return eventTime; } private static Document wrapNotification(final Document notificationContent, final Date eventTime) { diff --git a/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/netconf/notifications/impl/ops/CreateSubscription.java b/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/netconf/notifications/impl/ops/CreateSubscription.java index 559dbb2492..d1a46a67bd 100644 --- a/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/netconf/notifications/impl/ops/CreateSubscription.java +++ b/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/netconf/notifications/impl/ops/CreateSubscription.java @@ -11,6 +11,7 @@ package org.opendaylight.netconf.notifications.impl.ops; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; +import java.util.Date; import java.util.List; import org.opendaylight.controller.config.util.xml.DocumentedException; import org.opendaylight.controller.config.util.xml.XmlElement; @@ -24,6 +25,7 @@ import org.opendaylight.netconf.notifications.NetconfNotificationRegistry; import org.opendaylight.netconf.notifications.NotificationListenerRegistration; import org.opendaylight.netconf.notifications.impl.NetconfNotificationManager; import org.opendaylight.netconf.util.mapping.AbstractSingletonNetconfOperation; +import org.opendaylight.netconf.util.messages.SubtreeFilter; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInput; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType; import org.slf4j.Logger; @@ -58,9 +60,7 @@ public class CreateSubscription extends AbstractSingletonNetconfOperation implem // Binding doesn't support anyxml nodes yet, so filter could not be retrieved // xml -> normalized node -> CreateSubscriptionInput conversion could be slower than current approach - // FIXME filter could be supported same way as netconf server filters get and get-config results final Optional filter = operationElement.getOnlyChildElementWithSameNamespaceOptionally("filter"); - Preconditions.checkArgument(filter.isPresent() == false, "Filter element not yet supported"); // Replay not supported final Optional startTime = operationElement.getOnlyChildElementWithSameNamespaceOptionally("startTime"); @@ -79,7 +79,7 @@ public class CreateSubscription extends AbstractSingletonNetconfOperation implem } final NotificationListenerRegistration notificationListenerRegistration = - notifications.registerNotificationListener(streamNameType, new NotificationSubscription(netconfSession)); + notifications.registerNotificationListener(streamNameType, new NotificationSubscription(netconfSession, filter)); subscriptions.add(notificationListenerRegistration); return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); @@ -116,14 +116,29 @@ public class CreateSubscription extends AbstractSingletonNetconfOperation implem private static class NotificationSubscription implements NetconfNotificationListener { private final NetconfSession currentSession; + private final Optional filter; - public NotificationSubscription(final NetconfSession currentSession) { + public NotificationSubscription(final NetconfSession currentSession, final Optional filter) { this.currentSession = currentSession; + this.filter = filter; } @Override public void onNotification(final StreamNameType stream, final NetconfNotification notification) { - currentSession.sendMessage(notification); + if (filter.isPresent()) { + try { + final Optional filtered = SubtreeFilter.applySubtreeNotificationFilter(this.filter.get(), notification.getDocument()); + if (filtered.isPresent()) { + final Date eventTime = notification.getEventTime(); + currentSession.sendMessage(new NetconfNotification(filtered.get(), eventTime)); + } + } catch (DocumentedException e) { + LOG.warn(e.toString()); + currentSession.sendMessage(notification); + } + } else { + currentSession.sendMessage(notification); + } } } } diff --git a/netconf/netconf-topology/pom.xml b/netconf/netconf-topology/pom.xml index 41184f7d09..08b0dbac78 100644 --- a/netconf/netconf-topology/pom.xml +++ b/netconf/netconf-topology/pom.xml @@ -56,10 +56,6 @@ org.opendaylight.yangtools yang-parser-impl - - org.opendaylight.controller - yang-jmx-generator-plugin - org.opendaylight.netconf sal-netconf-connector diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java index bfc919e595..7a0d0f7dbb 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java @@ -266,11 +266,11 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address); RemoteDeviceHandler salFacade = - createSalFacade(remoteDeviceId, domBroker, bindingAwareBroker, defaultRequestTimeoutMillis); + createSalFacade(remoteDeviceId, domBroker, bindingAwareBroker); if (keepaliveDelay > 0) { LOG.warn("Adding keepalive facade, for device {}", nodeId); - salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay); + salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay, defaultRequestTimeoutMillis); } final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node); @@ -393,7 +393,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin .build(); } - protected abstract RemoteDeviceHandler createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker, long defaultRequestTimeoutMillis); + protected abstract RemoteDeviceHandler createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker); @Override public abstract ConnectionStatusListenerRegistration registerConnectionStatusListener(NodeId node, RemoteDeviceHandler listener); diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java index 04c95b49aa..1612c7d9fc 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java @@ -149,11 +149,11 @@ public class ClusteredNetconfTopology extends AbstractNetconfTopology implements RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address); RemoteDeviceHandler salFacade = - createSalFacade(remoteDeviceId, domBroker, bindingAwareBroker, defaultRequestTimeoutMillis); + createSalFacade(remoteDeviceId, domBroker, bindingAwareBroker); if (keepaliveDelay > 0) { LOG.warn("Adding keepalive facade, for device {}", nodeId); - salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay); + salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay, defaultRequestTimeoutMillis); } final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node); @@ -165,8 +165,8 @@ public class ClusteredNetconfTopology extends AbstractNetconfTopology implements } @Override - protected RemoteDeviceHandler createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker, long defaultRequestTimeoutMillis) { - return new TopologyMountPointFacade(topologyId, id, domBroker, bindingBroker, defaultRequestTimeoutMillis); + protected RemoteDeviceHandler createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker) { + return new TopologyMountPointFacade(topologyId, id, domBroker, bindingBroker); } @Override diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java index 33b468ce2b..c1e41189e3 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java @@ -80,8 +80,8 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology implements Data } @Override - protected RemoteDeviceHandler createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker, long defaultRequestTimeoutMillis) { - return new NetconfDeviceSalFacade(id, domBroker, bindingAwareBroker, defaultRequestTimeoutMillis); + protected RemoteDeviceHandler createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker) { + return new NetconfDeviceSalFacade(id, domBroker, bindingAwareBroker); } @Override diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceMasterDataBroker.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceMasterDataBroker.java index f210820ccd..dc292d33eb 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceMasterDataBroker.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceMasterDataBroker.java @@ -57,9 +57,9 @@ public class NetconfDeviceMasterDataBroker implements ProxyNetconfDeviceDataBrok public NetconfDeviceMasterDataBroker(final ActorSystem actorSystem, final RemoteDeviceId id, final SchemaContext schemaContext, final DOMRpcService rpc, - final NetconfSessionPreferences netconfSessionPreferences, final long requestTimeoutMillis) { + final NetconfSessionPreferences netconfSessionPreferences) { this.id = id; - delegateBroker = new NetconfDeviceDataBroker(id, schemaContext, rpc, netconfSessionPreferences, requestTimeoutMillis); + delegateBroker = new NetconfDeviceDataBroker(id, schemaContext, rpc, netconfSessionPreferences); this.actorSystem = actorSystem; // only ever need 1 readTx since it doesnt need to be closed diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacade.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacade.java index 269db6907b..c79627be5a 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacade.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacade.java @@ -43,7 +43,6 @@ public class TopologyMountPointFacade implements AutoCloseable, RemoteDeviceHand private final RemoteDeviceId id; private final Broker domBroker; private final BindingAwareBroker bindingBroker; - private final long defaultRequestTimeoutMillis; private SchemaContext remoteSchemaContext = null; private NetconfSessionPreferences netconfSessionPreferences = null; @@ -58,13 +57,11 @@ public class TopologyMountPointFacade implements AutoCloseable, RemoteDeviceHand public TopologyMountPointFacade(final String topologyId, final RemoteDeviceId id, final Broker domBroker, - final BindingAwareBroker bindingBroker, - long defaultRequestTimeoutMillis) { + final BindingAwareBroker bindingBroker) { this.topologyId = topologyId; this.id = id; this.domBroker = domBroker; this.bindingBroker = bindingBroker; - this.defaultRequestTimeoutMillis = defaultRequestTimeoutMillis; this.salProvider = new ClusteredNetconfDeviceMountInstanceProxy(id); registerToSal(domBroker); } @@ -124,7 +121,7 @@ public class TopologyMountPointFacade implements AutoCloseable, RemoteDeviceHand deviceDataBroker = TypedActor.get(context).typedActorOf(new TypedProps<>(ProxyNetconfDeviceDataBroker.class, new Creator() { @Override public NetconfDeviceMasterDataBroker create() throws Exception { - return new NetconfDeviceMasterDataBroker(actorSystem, id, remoteSchemaContext, deviceRpc, netconfSessionPreferences, defaultRequestTimeoutMillis); + return new NetconfDeviceMasterDataBroker(actorSystem, id, remoteSchemaContext, deviceRpc, netconfSessionPreferences); } }), MOUNT_POINT); LOG.debug("Master data broker registered on path {}", TypedActor.get(actorSystem).getActorRefFor(deviceDataBroker).path()); diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java index a29d95eb1a..2e16cca1cb 100644 --- a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java +++ b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java @@ -287,7 +287,7 @@ public class AbstractNetconfTopologyTest { } @Override - protected RemoteDeviceHandler createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker, long defaultRequestTimeoutMillis) { + protected RemoteDeviceHandler createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker) { return salFacade; } diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacadeTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacadeTest.java index 2b4b37418a..68342a56e5 100644 --- a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacadeTest.java +++ b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/TopologyMountPointFacadeTest.java @@ -48,7 +48,7 @@ public class TopologyMountPointFacadeTest { MockitoAnnotations.initMocks(this); - mountPointFacade = new TopologyMountPointFacade(TOPOLOGY_ID, REMOTE_DEVICE_ID, domBroker, bindingBroker, 1L); + mountPointFacade = new TopologyMountPointFacade(TOPOLOGY_ID, REMOTE_DEVICE_ID, domBroker, bindingBroker); mountPointFacade.registerConnectionStatusListener(connectionStatusListener1); mountPointFacade.registerConnectionStatusListener(connectionStatusListener2); diff --git a/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/messages/NetconfMessageHeader.java b/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/messages/NetconfMessageHeader.java deleted file mode 100644 index 8a425c2193..0000000000 --- a/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/messages/NetconfMessageHeader.java +++ /dev/null @@ -1,59 +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.netconf.util.messages; - -import com.google.common.base.Charsets; -import com.google.common.base.Preconditions; -import java.nio.ByteBuffer; - -/** - * Netconf message header is used only when chunked framing mechanism is - * supported. The header consists of only the length field. - */ -@Deprecated -public final class NetconfMessageHeader { - // \n#\n - private static final byte[] HEADER_START = new byte[] { (byte) 0x0a, (byte) 0x23 }; - private static final byte HEADER_END = (byte) 0x0a; - private final long length; - - public NetconfMessageHeader(final long length) { - Preconditions.checkArgument(length < Integer.MAX_VALUE && length > 0); - this.length = length; - } - - public byte[] toBytes() { - return toBytes(this.length); - } - - // FIXME: improve precision to long - public int getLength() { - return (int) this.length; - } - - public static NetconfMessageHeader fromBytes(final byte[] bytes) { - // the length is variable therefore bytes between headerBegin and - // headerEnd mark the length - // the length should be only numbers and therefore easily parsed with - // ASCII - long length = Long.parseLong(Charsets.US_ASCII.decode( - ByteBuffer.wrap(bytes, HEADER_START.length, bytes.length - HEADER_START.length - 1)).toString()); - - return new NetconfMessageHeader(length); - } - - public static byte[] toBytes(final long length) { - final byte[] l = String.valueOf(length).getBytes(Charsets.US_ASCII); - final byte[] h = new byte[HEADER_START.length + l.length + 1]; - System.arraycopy(HEADER_START, 0, h, 0, HEADER_START.length); - System.arraycopy(l, 0, h, HEADER_START.length, l.length); - System.arraycopy(new byte[] { HEADER_END }, 0, h, HEADER_START.length + l.length, 1); - return h; - } -} diff --git a/netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/SubtreeFilter.java b/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/messages/SubtreeFilter.java similarity index 73% rename from netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/SubtreeFilter.java rename to netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/messages/SubtreeFilter.java index d1466dcdd5..949e63d661 100644 --- a/netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/SubtreeFilter.java +++ b/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/messages/SubtreeFilter.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.netconf.impl; +package org.opendaylight.netconf.util.messages; import com.google.common.base.Optional; import java.io.IOException; @@ -14,8 +14,8 @@ import java.util.Map; import org.opendaylight.controller.config.util.xml.DocumentedException; import org.opendaylight.controller.config.util.xml.XmlElement; import org.opendaylight.controller.config.util.xml.XmlUtil; -import org.opendaylight.netconf.util.mapping.AbstractNetconfOperation.OperationNameAndNamespace; import org.opendaylight.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.netconf.util.mapping.AbstractNetconfOperation.OperationNameAndNamespace; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Attr; @@ -30,7 +30,7 @@ import org.xml.sax.SAXException; public class SubtreeFilter { private static final Logger LOG = LoggerFactory.getLogger(SubtreeFilter.class); - static Document applySubtreeFilter(Document requestDocument, Document rpcReply) throws DocumentedException { + public static Document applyRpcSubtreeFilter(Document requestDocument, Document rpcReply) throws DocumentedException { OperationNameAndNamespace operationNameAndNamespace = new OperationNameAndNamespace(requestDocument); if (XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0.equals(operationNameAndNamespace.getNamespace()) && XmlNetconfConstants.GET.equals(operationNameAndNamespace.getOperationName()) || @@ -43,16 +43,9 @@ public class SubtreeFilter { return rpcReply; } - // FIXME: rpcReply document must be reread otherwise some nodes do not inherit namespaces. (services/service) - try { - rpcReply = XmlUtil.readXmlToDocument(XmlUtil.toString(rpcReply, true)); - } catch (SAXException | IOException e) { - LOG.error("Cannot transform document", e); - throw new DocumentedException("Cannot transform document" + e); - } + rpcReply = reReadDocument(rpcReply); XmlElement filter = maybeFilter.get(); - if ("subtree".equals(filter.getAttribute("type"))|| - "subtree".equals(filter.getAttribute("type", XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0))) { + if (isSupported(filter)) { // do return filtered(maybeFilter.get(), rpcReply); @@ -62,6 +55,68 @@ public class SubtreeFilter { return rpcReply; // return identical document } + /** + * Filters notification content. If filter type isn't of type "subtree", returns unchanged notification content. + * If no match is found, absent is returned. + * @param filter filter + * @param notification notification + * @return document containing filtered notification content + * @throws DocumentedException + */ + public static Optional applySubtreeNotificationFilter(XmlElement filter, Document notification) throws DocumentedException { + notification = reReadDocument(notification); + removeEventTimeNode(notification); + if (isSupported(filter)) { + return Optional.fromNullable(filteredNotification(filter, notification)); + } + return Optional.of(extractNotificationContent(notification)); + } + + private static Document reReadDocument(Document notification) throws DocumentedException { + // FIXME: rpcReply document must be reread otherwise some nodes do not inherit namespaces. (services/service) + try { + notification = XmlUtil.readXmlToDocument(XmlUtil.toString(notification, true)); + } catch (SAXException | IOException e) { + LOG.error("Cannot transform document", e); + throw new DocumentedException("Cannot transform document" + e); + } + return notification; + } + + private static void removeEventTimeNode(Document document) { + final Node eventTimeNode = document.getDocumentElement().getElementsByTagNameNS( + XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_NOTIFICATION_1_0, XmlNetconfConstants.EVENT_TIME).item(0); + document.getDocumentElement().removeChild(eventTimeNode); + } + + private static boolean isSupported(XmlElement filter) { + return "subtree".equals(filter.getAttribute("type"))|| + "subtree".equals(filter.getAttribute("type", XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0)); + } + + private static Document extractNotificationContent(Document notification) throws DocumentedException { + XmlElement root = XmlElement.fromDomElement(notification.getDocumentElement()); + XmlElement content = root.getOnlyChildElement(); + notification.removeChild(root.getDomElement()); + notification.appendChild(content.getDomElement()); + return notification; + } + + private static Document filteredNotification(XmlElement filter, Document originalNotification) throws DocumentedException { + Document result = XmlUtil.newDocument(); + XmlElement dataSrc = XmlElement.fromDomDocument(originalNotification); + Element dataDst = (Element) result.importNode(dataSrc.getDomElement(), false); + for (XmlElement filterChild : filter.getChildElements()) { + addSubtree2(filterChild, dataSrc.getOnlyChildElement(), XmlElement.fromDomElement(dataDst)); + } + if(dataDst.getFirstChild() != null) { + result.appendChild(dataDst.getFirstChild()); + return result; + } else { + return null; + } + } + private static Document filtered(XmlElement filter, Document originalReplyDocument) throws DocumentedException { Document result = XmlUtil.newDocument(); // even if filter is empty, copy /rpc/data diff --git a/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/NetconfMessageHeaderTest.java b/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/NetconfMessageHeaderTest.java deleted file mode 100644 index 1c09b959b8..0000000000 --- a/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/NetconfMessageHeaderTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2014 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.netconf.util.messages; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import com.google.common.base.Charsets; -import org.junit.Test; - -@Deprecated -public class NetconfMessageHeaderTest { - @Test - public void testGet() throws Exception { - NetconfMessageHeader header = new NetconfMessageHeader(10); - assertEquals(header.getLength(), 10); - - byte[] expectedValue = "\n#10\n".getBytes(Charsets.US_ASCII); - assertArrayEquals(expectedValue, header.toBytes()); - } -} diff --git a/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/SubtreeFilterNotificationTest.java b/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/SubtreeFilterNotificationTest.java new file mode 100644 index 0000000000..ac7d83ce37 --- /dev/null +++ b/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/SubtreeFilterNotificationTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 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.netconf.util.messages; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.google.common.base.Optional; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.opendaylight.controller.config.util.xml.XmlElement; +import org.opendaylight.controller.config.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +@RunWith(value = Parameterized.class) +public class SubtreeFilterNotificationTest { + private static final Logger LOG = LoggerFactory.getLogger(SubtreeFilterRpcTest.class); + + private final int directoryIndex; + + @Parameters + public static Collection data() { + List result = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + result.add(new Object[]{i}); + } + return result; + } + + public SubtreeFilterNotificationTest(int directoryIndex) { + this.directoryIndex = directoryIndex; + } + + @Before + public void setUp(){ + XMLUnit.setIgnoreWhitespace(true); + } + + @Test + public void testFilterNotification() throws Exception { + XmlElement filter = XmlElement.fromDomDocument(getDocument("filter.xml")); + Document preFilterDocument = getDocument("pre-filter.xml"); + Document postFilterDocument = getDocument("post-filter.xml"); + Optional actualPostFilterDocumentOpt = SubtreeFilter.applySubtreeNotificationFilter(filter, preFilterDocument); + if(actualPostFilterDocumentOpt.isPresent()) { + Document actualPostFilterDocument = actualPostFilterDocumentOpt.get(); + LOG.info("Actual document: {}", XmlUtil.toString(actualPostFilterDocument)); + Diff diff = XMLUnit.compareXML(postFilterDocument, actualPostFilterDocument); + assertTrue(diff.toString(), diff.similar()); + } else { + assertEquals("empty", XmlElement.fromDomDocument(postFilterDocument).getName()); + } + } + + public Document getDocument(String fileName) throws SAXException, IOException { + return XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/subtree/notification/" + directoryIndex + "/" + + fileName)); + } +} diff --git a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/SubtreeFilterTest.java b/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/SubtreeFilterRpcTest.java similarity index 86% rename from netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/SubtreeFilterTest.java rename to netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/SubtreeFilterRpcTest.java index 45ca8c3c36..e486c75f2e 100644 --- a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/SubtreeFilterTest.java +++ b/netconf/netconf-util/src/test/java/org/opendaylight/netconf/util/messages/SubtreeFilterRpcTest.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.netconf.impl; +package org.opendaylight.netconf.util.messages; import static org.junit.Assert.assertTrue; @@ -28,8 +28,8 @@ import org.w3c.dom.Document; import org.xml.sax.SAXException; @RunWith(value = Parameterized.class) -public class SubtreeFilterTest { - private static final Logger LOG = LoggerFactory.getLogger(SubtreeFilterTest.class); +public class SubtreeFilterRpcTest { + private static final Logger LOG = LoggerFactory.getLogger(SubtreeFilterRpcTest.class); private final int directoryIndex; @@ -42,7 +42,7 @@ public class SubtreeFilterTest { return result; } - public SubtreeFilterTest(int directoryIndex) { + public SubtreeFilterRpcTest(int directoryIndex) { this.directoryIndex = directoryIndex; } @@ -56,7 +56,7 @@ public class SubtreeFilterTest { Document requestDocument = getDocument("request.xml"); Document preFilterDocument = getDocument("pre-filter.xml"); Document postFilterDocument = getDocument("post-filter.xml"); - Document actualPostFilterDocument = SubtreeFilter.applySubtreeFilter(requestDocument, preFilterDocument); + Document actualPostFilterDocument = SubtreeFilter.applyRpcSubtreeFilter(requestDocument, preFilterDocument); LOG.info("Actual document: {}", XmlUtil.toString(actualPostFilterDocument)); Diff diff = XMLUnit.compareXML(postFilterDocument, actualPostFilterDocument); assertTrue(diff.toString(), diff.similar()); @@ -64,7 +64,7 @@ public class SubtreeFilterTest { } public Document getDocument(String fileName) throws SAXException, IOException { - return XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/subtree/" + directoryIndex + "/" + + return XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/subtree/rpc/" + directoryIndex + "/" + fileName)); } } diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/0/filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/0/filter.xml new file mode 100644 index 0000000000..83b3fcb2e8 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/0/filter.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/0/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/0/post-filter.xml new file mode 100644 index 0000000000..9f1667a4c8 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/0/post-filter.xml @@ -0,0 +1,14 @@ + + + admin + 2 + + + + diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/0/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/0/pre-filter.xml new file mode 100644 index 0000000000..af5368ea80 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/0/pre-filter.xml @@ -0,0 +1,15 @@ + + + + admin + 2 + 127.0.0.1 + + 2016-03-17T13:15:12+01:00 + diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/1/filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/1/filter.xml new file mode 100644 index 0000000000..ca976c8611 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/1/filter.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/1/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/1/post-filter.xml new file mode 100644 index 0000000000..92c9db839a --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/1/post-filter.xml @@ -0,0 +1,12 @@ + + + admin + 2 + 127.0.0.1 + diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/1/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/1/pre-filter.xml new file mode 100644 index 0000000000..af5368ea80 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/1/pre-filter.xml @@ -0,0 +1,15 @@ + + + + admin + 2 + 127.0.0.1 + + 2016-03-17T13:15:12+01:00 + diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/2/filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/2/filter.xml new file mode 100644 index 0000000000..ca976c8611 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/2/filter.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/2/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/2/post-filter.xml new file mode 100644 index 0000000000..3755dd4b83 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/2/post-filter.xml @@ -0,0 +1,12 @@ + + + admin + 2 + 127.0.0.1 + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/2/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/2/pre-filter.xml new file mode 100644 index 0000000000..66e7b561f3 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/2/pre-filter.xml @@ -0,0 +1,15 @@ + + + + admin + 2 + 127.0.0.1 + + 2016-03-17T13:15:04+01:00 + diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/3/filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/3/filter.xml new file mode 100644 index 0000000000..83b3fcb2e8 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/3/filter.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/3/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/3/post-filter.xml new file mode 100644 index 0000000000..4c9b4126cb --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/3/post-filter.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/3/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/3/pre-filter.xml new file mode 100644 index 0000000000..66e7b561f3 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/3/pre-filter.xml @@ -0,0 +1,15 @@ + + + + admin + 2 + 127.0.0.1 + + 2016-03-17T13:15:04+01:00 + diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/4/filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/4/filter.xml new file mode 100644 index 0000000000..d8c908cefb --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/4/filter.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/4/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/4/post-filter.xml new file mode 100644 index 0000000000..026f7976ff --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/4/post-filter.xml @@ -0,0 +1,6 @@ + + + admin + 2 + 127.0.0.1 + \ No newline at end of file diff --git a/netconf/netconf-util/src/test/resources/subtree/notification/4/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/notification/4/pre-filter.xml new file mode 100644 index 0000000000..10f229dfb0 --- /dev/null +++ b/netconf/netconf-util/src/test/resources/subtree/notification/4/pre-filter.xml @@ -0,0 +1,15 @@ + + + + admin + 2 + 127.0.0.1 + + 2016-03-17T13:15:12+01:00 + \ No newline at end of file diff --git a/netconf/netconf-impl/src/test/resources/subtree/0/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/0/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/0/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/0/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/0/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/0/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/0/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/0/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/0/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/0/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/0/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/0/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/1/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/1/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/1/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/1/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/1/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/1/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/1/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/1/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/1/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/1/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/1/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/1/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/10/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/10/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/10/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/10/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/10/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/10/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/10/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/10/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/10/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/10/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/10/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/10/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/2/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/2/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/2/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/2/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/2/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/2/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/2/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/2/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/2/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/2/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/2/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/2/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/3/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/3/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/3/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/3/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/3/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/3/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/3/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/3/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/3/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/3/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/3/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/3/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/4/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/4/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/4/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/4/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/4/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/4/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/4/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/4/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/4/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/4/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/4/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/4/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/5/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/5/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/5/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/5/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/5/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/5/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/5/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/5/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/5/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/5/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/5/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/5/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/6/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/6/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/6/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/6/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/6/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/6/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/6/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/6/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/6/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/6/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/6/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/6/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/7/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/7/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/7/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/7/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/7/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/7/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/7/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/7/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/7/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/7/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/7/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/7/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/8/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/8/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/8/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/8/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/8/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/8/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/8/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/8/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/8/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/8/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/8/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/8/request.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/9/post-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/9/post-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/9/post-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/9/post-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/9/pre-filter.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/9/pre-filter.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/9/pre-filter.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/9/pre-filter.xml diff --git a/netconf/netconf-impl/src/test/resources/subtree/9/request.xml b/netconf/netconf-util/src/test/resources/subtree/rpc/9/request.xml similarity index 100% rename from netconf/netconf-impl/src/test/resources/subtree/9/request.xml rename to netconf/netconf-util/src/test/resources/subtree/rpc/9/request.xml diff --git a/netconf/sal-netconf-connector/pom.xml b/netconf/sal-netconf-connector/pom.xml index ee1640e33d..40fe3b2f70 100644 --- a/netconf/sal-netconf-connector/pom.xml +++ b/netconf/sal-netconf-connector/pom.xml @@ -191,18 +191,6 @@ org.hamcrest hamcrest-core - - org.powermock - powermock-api-mockito - 1.6.4 - test - - - org.powermock - powermock-module-junit4 - 1.6.4 - test - diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java index 785be9954d..d7222c1bb2 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java @@ -192,14 +192,14 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co final ExecutorService globalProcessingExecutor = processingExecutor.getExecutor(); RemoteDeviceHandler salFacade - = new NetconfDeviceSalFacade(id, domRegistry, bindingRegistry, getDefaultRequestTimeoutMillis()); + = new NetconfDeviceSalFacade(id, domRegistry, bindingRegistry); final Long keepaliveDelay = getKeepaliveDelay(); if (shouldSendKeepalive()) { // Keepalive executor is optional for now and a default instance is supported final ScheduledExecutorService executor = keepaliveExecutor == null ? DEFAULT_KEEPALIVE_EXECUTOR : keepaliveExecutor.getExecutor(); - salFacade = new KeepaliveSalFacade(id, salFacade, executor, keepaliveDelay); + salFacade = new KeepaliveSalFacade(id, salFacade, executor, keepaliveDelay, getDefaultRequestTimeoutMillis()); } // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc. diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java index bb63554d54..1b8a820f4f 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java @@ -143,7 +143,7 @@ public class NetconfDevice implements RemoteDevice listener; private final NetconfDeviceCapabilities capabilities; - public RecursiveSchemaSetup(final DeviceSources deviceSources, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceCommunicator listener) { + public SchemaSetup(final DeviceSources deviceSources, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceCommunicator listener) { this.deviceSources = deviceSources; this.remoteSessionCapabilities = remoteSessionCapabilities; this.listener = listener; @@ -391,37 +391,23 @@ public class NetconfDevice implements RemoteDevice requiredSources) { - LOG.trace("{}: Trying to build schema context from {}", id, requiredSources); - - // If no more sources, fail - if(requiredSources.isEmpty()) { - final IllegalStateException cause = new IllegalStateException(id + ": No more sources for schema context"); - handleSalInitializationFailure(cause, listener); - salFacade.onDeviceFailed(cause); - return; - } - - final CheckedFuture schemaBuilderFuture = schemaContextFactory.createSchemaContext(requiredSources); - - final FutureCallback RecursiveSchemaBuilderCallback = new FutureCallback() { - - @Override - public void onSuccess(final SchemaContext result) { + private void setUpSchema(Collection requiredSources) { + while (!requiredSources.isEmpty()) { + LOG.trace("{}: Trying to build schema context from {}", id, requiredSources); + try { + final CheckedFuture schemaBuilderFuture = schemaContextFactory.createSchemaContext(requiredSources); + final SchemaContext result = schemaBuilderFuture.checkedGet(); LOG.debug("{}: Schema context built successfully from {}", id, requiredSources); final Collection filteredQNames = Sets.difference(deviceSources.getRequiredSourcesQName(), capabilities.getUnresolvedCapabilites().keySet()); capabilities.addCapabilities(filteredQNames); capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps()); handleSalInitializationSuccess(result, remoteSessionCapabilities, getDeviceSpecificRpc(result)); - } - - @Override - public void onFailure(final Throwable t) { - // In case source missing, try without it - if (t instanceof MissingSchemaSourceException) { + return; + } catch (Throwable t) { + if (t instanceof MissingSchemaSourceException){ + // In case source missing, try without it final SourceIdentifier missingSource = ((MissingSchemaSourceException) t).getSourceId(); LOG.warn("{}: Unable to build schema context, missing source {}, will reattempt without it", id, missingSource); LOG.debug("{}: Unable to build schema context, missing source {}, will reattempt without it", t); @@ -429,27 +415,29 @@ public class NetconfDevice implements RemoteDevice unresolvedSources = resolutionException.getUnsatisfiedImports().keySet(); capabilities.addUnresolvedCapabilities(getQNameFromSourceIdentifiers(unresolvedSources), UnavailableCapability.FailureReason.UnableToResolve); LOG.warn("{}: Unable to build schema context, unsatisfied imports {}, will reattempt with resolved only", id, resolutionException.getUnsatisfiedImports()); LOG.debug("{}: Unable to build schema context, unsatisfied imports {}, will reattempt with resolved only", resolutionException); - setUpSchema(resolutionException.getResolvedSources()); - // unknown error, fail + requiredSources = resolutionException.getResolvedSources(); } else { + // unknown error, fail handleSalInitializationFailure(t, listener); + return; } } - }; - - Futures.addCallback(schemaBuilderFuture, RecursiveSchemaBuilderCallback); + } + // No more sources, fail + final IllegalStateException cause = new IllegalStateException(id + ": No more sources for schema context"); + handleSalInitializationFailure(cause, listener); + salFacade.onDeviceFailed(cause); } + protected NetconfDeviceRpc getDeviceSpecificRpc(final SchemaContext result) { return new NetconfDeviceRpc(result, listener, new NetconfMessageTransformer(result, true)); } diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java index dc2b5dff42..c450ac68fe 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java @@ -51,28 +51,33 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler salFacade; private final ScheduledExecutorService executor; private final long keepaliveDelaySeconds; private final ResetKeepalive resetKeepaliveTask; + private final long defaultRequestTimeoutMillis; private volatile NetconfDeviceCommunicator listener; private volatile ScheduledFuture currentKeepalive; private volatile DOMRpcService currentDeviceRpc; public KeepaliveSalFacade(final RemoteDeviceId id, final RemoteDeviceHandler salFacade, - final ScheduledExecutorService executor, final long keepaliveDelaySeconds) { + final ScheduledExecutorService executor, final long keepaliveDelaySeconds, final long defaultRequestTimeoutMillis) { this.id = id; this.salFacade = salFacade; this.executor = executor; this.keepaliveDelaySeconds = keepaliveDelaySeconds; + this.defaultRequestTimeoutMillis = defaultRequestTimeoutMillis; this.resetKeepaliveTask = new ResetKeepalive(); } public KeepaliveSalFacade(final RemoteDeviceId id, final RemoteDeviceHandler salFacade, final ScheduledExecutorService executor) { - this(id, salFacade, executor, DEFAULT_DELAY); + this(id, salFacade, executor, DEFAULT_DELAY, DEFAULT_TRANSACTION_TIMEOUT_MILLI); } /** @@ -118,7 +123,7 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler { + private class ResetKeepalive implements FutureCallback { @Override public void onSuccess(@Nullable final DOMRpcResult result) { // No matter what response we got, rpc-reply or rpc-error, we got it from device so the netconf session is OK @@ -223,24 +228,51 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler rpcResultFuture; + + public RequestTimeoutTask(final CheckedFuture rpcResultFuture) { + this.rpcResultFuture = rpcResultFuture; + } + + @Override + public void run() { + if (!rpcResultFuture.isDone()) { + rpcResultFuture.cancel(true); + } + } + } + /** - * DOMRpcService proxy that attaches reset-keepalive-task to each RPC invocation. + * DOMRpcService proxy that attaches reset-keepalive-task and schedule + * request-timeout-task to each RPC invocation. */ private static final class KeepaliveDOMRpcService implements DOMRpcService { private final DOMRpcService deviceRpc; private ResetKeepalive resetKeepaliveTask; + private final long defaultRequestTimeoutMillis; + private final ScheduledExecutorService executor; - public KeepaliveDOMRpcService(final DOMRpcService deviceRpc, final ResetKeepalive resetKeepaliveTask) { + public KeepaliveDOMRpcService(final DOMRpcService deviceRpc, final ResetKeepalive resetKeepaliveTask, + final long defaultRequestTimeoutMillis, final ScheduledExecutorService executor) { this.deviceRpc = deviceRpc; this.resetKeepaliveTask = resetKeepaliveTask; + this.defaultRequestTimeoutMillis = defaultRequestTimeoutMillis; + this.executor = executor; } @Nonnull @@ -248,6 +280,10 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler invokeRpc(@Nonnull final SchemaPath type, final NormalizedNode input) { final CheckedFuture domRpcResultDOMRpcExceptionCheckedFuture = deviceRpc.invokeRpc(type, input); Futures.addCallback(domRpcResultDOMRpcExceptionCheckedFuture, resetKeepaliveTask); + + final RequestTimeoutTask timeoutTask = new RequestTimeoutTask(domRpcResultDOMRpcExceptionCheckedFuture); + executor.schedule(timeoutTask, defaultRequestTimeoutMillis, TimeUnit.MILLISECONDS); + return domRpcResultDOMRpcExceptionCheckedFuture; } diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBroker.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBroker.java index 7283cae9b8..421e52da71 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBroker.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBroker.java @@ -36,16 +36,14 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; public final class NetconfDeviceDataBroker implements DOMDataBroker { private final RemoteDeviceId id; private final NetconfBaseOps netconfOps; - private final long requestTimeoutMillis; private final boolean rollbackSupport; private boolean candidateSupported; private boolean runningWritable; - public NetconfDeviceDataBroker(final RemoteDeviceId id, final SchemaContext schemaContext, final DOMRpcService rpc, final NetconfSessionPreferences netconfSessionPreferences, long requestTimeoutMillis) { + public NetconfDeviceDataBroker(final RemoteDeviceId id, final SchemaContext schemaContext, final DOMRpcService rpc, final NetconfSessionPreferences netconfSessionPreferences) { this.id = id; this.netconfOps = new NetconfBaseOps(rpc, schemaContext); - this.requestTimeoutMillis = requestTimeoutMillis; // get specific attributes from netconf preferences and get rid of it // no need to keep the entire preferences object, its quite big with all the capability QNames candidateSupported = netconfSessionPreferences.isCandidateSupported(); @@ -57,7 +55,7 @@ public final class NetconfDeviceDataBroker implements DOMDataBroker { @Override public DOMDataReadOnlyTransaction newReadOnlyTransaction() { - return new ReadOnlyTx(netconfOps, id, requestTimeoutMillis); + return new ReadOnlyTx(netconfOps, id); } @Override @@ -69,12 +67,12 @@ public final class NetconfDeviceDataBroker implements DOMDataBroker { public DOMDataWriteTransaction newWriteOnlyTransaction() { if(candidateSupported) { if(runningWritable) { - return new WriteCandidateRunningTx(id, netconfOps, rollbackSupport, requestTimeoutMillis); + return new WriteCandidateRunningTx(id, netconfOps, rollbackSupport); } else { - return new WriteCandidateTx(id, netconfOps, rollbackSupport, requestTimeoutMillis); + return new WriteCandidateTx(id, netconfOps, rollbackSupport); } } else { - return new WriteRunningTx(id, netconfOps, rollbackSupport, requestTimeoutMillis); + return new WriteRunningTx(id, netconfOps, rollbackSupport); } } diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceSalFacade.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceSalFacade.java index 7bb3df08a5..2a817db7ec 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceSalFacade.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceSalFacade.java @@ -30,14 +30,12 @@ public final class NetconfDeviceSalFacade implements AutoCloseable, RemoteDevice private final RemoteDeviceId id; private final NetconfDeviceSalProvider salProvider; - private final long defaultRequestTimeoutMillis; private final List salRegistrations = Lists.newArrayList(); - public NetconfDeviceSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker, long defaultRequestTimeoutMillis) { + public NetconfDeviceSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker) { this.id = id; this.salProvider = new NetconfDeviceSalProvider(id); - this.defaultRequestTimeoutMillis = defaultRequestTimeoutMillis; registerToSal(domBroker, bindingBroker); } @@ -55,7 +53,7 @@ public final class NetconfDeviceSalFacade implements AutoCloseable, RemoteDevice public synchronized void onDeviceConnected(final SchemaContext schemaContext, final NetconfSessionPreferences netconfSessionPreferences, final DOMRpcService deviceRpc) { - final DOMDataBroker domBroker = new NetconfDeviceDataBroker(id, schemaContext, deviceRpc, netconfSessionPreferences, defaultRequestTimeoutMillis); + final DOMDataBroker domBroker = new NetconfDeviceDataBroker(id, schemaContext, deviceRpc, netconfSessionPreferences); final NetconfDeviceNotificationService notificationService = new NetconfDeviceNotificationService(); diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/AbstractWriteTx.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/AbstractWriteTx.java index a12ba3a02a..3aeff93da4 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/AbstractWriteTx.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/AbstractWriteTx.java @@ -11,11 +11,8 @@ package org.opendaylight.netconf.sal.connect.netconf.sal.tx; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; @@ -29,7 +26,6 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; import org.opendaylight.yangtools.yang.data.api.schema.MixinNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,15 +33,13 @@ public abstract class AbstractWriteTx implements DOMDataWriteTransaction { private static final Logger LOG = LoggerFactory.getLogger(AbstractWriteTx.class); - protected final long defaultRequestTimeoutMillis; protected final RemoteDeviceId id; protected final NetconfBaseOps netOps; protected final boolean rollbackSupport; // Allow commit to be called only once protected boolean finished = false; - public AbstractWriteTx(final long requestTimeoutMillis, final NetconfBaseOps netOps, final RemoteDeviceId id, final boolean rollbackSupport) { - this.defaultRequestTimeoutMillis = requestTimeoutMillis; + public AbstractWriteTx(final NetconfBaseOps netOps, final RemoteDeviceId id, final boolean rollbackSupport) { this.netOps = netOps; this.id = id; this.rollbackSupport = rollbackSupport; @@ -176,18 +170,4 @@ public abstract class AbstractWriteTx implements DOMDataWriteTransaction { } protected abstract void editConfig(DataContainerChild editStructure, Optional defaultOperation) throws NetconfDocumentedException; - - - protected ListenableFuture perfomRequestWithTimeout(String operation, ListenableFuture future) { - try { - future.get(defaultRequestTimeoutMillis, TimeUnit.MILLISECONDS); - } catch (InterruptedException | ExecutionException e) { - LOG.error("{}: {} failed with error", operation, id, e); - return Futures.immediateFailedCheckedFuture(new RuntimeException(id + ": " + operation + " failed")); - } catch (TimeoutException e) { - LOG.warn("{}: Unable to {} after {} milliseconds", id, operation, defaultRequestTimeoutMillis, e); - return Futures.immediateFailedCheckedFuture(new SchemaSourceException(e.getMessage())); - } - return future; - } } diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTx.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTx.java index 28d75cdaa4..dda5485109 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTx.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTx.java @@ -16,9 +16,6 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; @@ -44,12 +41,9 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction { private final RemoteDeviceId id; private final FutureCallback loggingCallback; - private final long requestTimeoutMillis; - - public ReadOnlyTx(final NetconfBaseOps netconfOps, final RemoteDeviceId id, final long requestTimeoutMillis) { + public ReadOnlyTx(final NetconfBaseOps netconfOps, final RemoteDeviceId id) { this.netconfOps = netconfOps; this.id = id; - this.requestTimeoutMillis = requestTimeoutMillis; // Simple logging callback to log result of read operation loggingCallback = new FutureCallback() { @@ -84,10 +78,6 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction { } }); - if(!readWithTimeout("readConfigurationData", configRunning)) { - return null; - } - return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER); } @@ -119,10 +109,6 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction { } }); - if(!readWithTimeout("readOperationalData", configCandidate)) { - return null; - } - return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER); } @@ -161,18 +147,4 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction { public Object getIdentifier() { return this; } - - private boolean readWithTimeout(String operation, ListenableFuture future) { - try { - future.get(requestTimeoutMillis, TimeUnit.MILLISECONDS); - } catch (InterruptedException | ExecutionException e) { - LOG.error("{}: {} failed with error", id, operation, e); - throw new RuntimeException(id + ": readOperationalData failed"); - } catch (TimeoutException e) { - LOG.warn("{}: Unable to {} after {} milliseconds", id, operation, requestTimeoutMillis, e); - future.cancel(true); - return false; - } - return true; - } } diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTx.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTx.java index 0b9bb98e9c..c076d0b7a8 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTx.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTx.java @@ -29,8 +29,8 @@ public class WriteCandidateRunningTx extends WriteCandidateTx { private static final Logger LOG = LoggerFactory.getLogger(WriteCandidateRunningTx.class); - public WriteCandidateRunningTx(final RemoteDeviceId id, final NetconfBaseOps netOps, final boolean rollbackSupport, final long requestTimeoutMillis) { - super(id, netOps, rollbackSupport, requestTimeoutMillis); + public WriteCandidateRunningTx(final RemoteDeviceId id, final NetconfBaseOps netOps, final boolean rollbackSupport) { + super(id, netOps, rollbackSupport); } @Override @@ -46,13 +46,11 @@ public class WriteCandidateRunningTx extends WriteCandidateTx { } private void lockRunning() { - final String operation = "Lock Running"; try { - invokeBlocking(operation, new Function>() { + invokeBlocking("Lock running", new Function>() { @Override public ListenableFuture apply(final NetconfBaseOps input) { - return perfomRequestWithTimeout(operation, input.lockRunning(new NetconfRpcFutureCallback(operation, id))); - + return input.lockRunning(new NetconfRpcFutureCallback("Lock running", id)); } }); } catch (final NetconfDocumentedException e) { diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java index f607089dc0..b143a3bf8e 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java @@ -71,8 +71,8 @@ public class WriteCandidateTx extends AbstractWriteTx { } }; - public WriteCandidateTx(final RemoteDeviceId id, final NetconfBaseOps rpc, final boolean rollbackSupport, long requestTimeoutMillis) { - super(requestTimeoutMillis, rpc, id, rollbackSupport); + public WriteCandidateTx(final RemoteDeviceId id, final NetconfBaseOps rpc, final boolean rollbackSupport) { + super(rpc, id, rollbackSupport); } @Override @@ -95,12 +95,11 @@ public class WriteCandidateTx extends AbstractWriteTx { } private void lock() throws NetconfDocumentedException { - final String operation = "Lock candidate"; try { - invokeBlocking(operation, new Function>() { + invokeBlocking("Lock candidate", new Function>() { @Override public ListenableFuture apply(final NetconfBaseOps input) { - return perfomRequestWithTimeout(operation, input.lockCandidate(new NetconfRpcFutureCallback(operation, id))); + return input.lockCandidate(new NetconfRpcFutureCallback("Lock candidate", id)); } }); } catch (final NetconfDocumentedException e) { @@ -186,16 +185,14 @@ public class WriteCandidateTx extends AbstractWriteTx { @Override protected void editConfig(final DataContainerChild editStructure, final Optional defaultOperation) throws NetconfDocumentedException { - final String operation = "Edit candidate"; - invokeBlocking(operation, new Function>() { + invokeBlocking("Edit candidate", new Function>() { @Override public ListenableFuture apply(final NetconfBaseOps input) { - - return perfomRequestWithTimeout(operation, defaultOperation.isPresent() - ? input.editConfigCandidate(new NetconfRpcFutureCallback(operation, id), editStructure, defaultOperation.get(), - rollbackSupport) - : input.editConfigCandidate(new NetconfRpcFutureCallback(operation, id), editStructure, - rollbackSupport)); + return defaultOperation.isPresent() + ? input.editConfigCandidate(new NetconfRpcFutureCallback("Edit candidate", id), editStructure, defaultOperation.get(), + rollbackSupport) + : input.editConfigCandidate(new NetconfRpcFutureCallback("Edit candidate", id), editStructure, + rollbackSupport); } }); } diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTx.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTx.java index 1d0ff653ef..cf7594a7bc 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTx.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTx.java @@ -51,8 +51,8 @@ public class WriteRunningTx extends AbstractWriteTx { private static final Logger LOG = LoggerFactory.getLogger(WriteRunningTx.class); public WriteRunningTx(final RemoteDeviceId id, final NetconfBaseOps netOps, - final boolean rollbackSupport, long requestTimeoutMillis) { - super(requestTimeoutMillis, netOps, id, rollbackSupport); + final boolean rollbackSupport) { + super(netOps, id, rollbackSupport); } @Override @@ -61,12 +61,11 @@ public class WriteRunningTx extends AbstractWriteTx { } private void lock() { - final String operation = "Lock running"; try { - invokeBlocking(operation, new Function>() { + invokeBlocking("Lock running", new Function>() { @Override public ListenableFuture apply(final NetconfBaseOps input) { - return perfomRequestWithTimeout(operation, input.lockRunning(new NetconfRpcFutureCallback(operation, id))); + return input.lockRunning(new NetconfRpcFutureCallback("Lock running", id)); } }); } catch (final NetconfDocumentedException e) { @@ -97,14 +96,14 @@ public class WriteRunningTx extends AbstractWriteTx { @Override public synchronized CheckedFuture submit() { - final ListenableFuture commitFutureAsVoid = Futures.transform(commit(), new Function, Void>() { + final ListenableFuture commmitFutureAsVoid = Futures.transform(commit(), new Function, Void>() { @Override public Void apply(final RpcResult input) { return null; } }); - return Futures.makeChecked(commitFutureAsVoid, new Function() { + return Futures.makeChecked(commmitFutureAsVoid, new Function() { @Override public TransactionCommitFailedException apply(final Exception input) { return new TransactionCommitFailedException("Submit of transaction " + getIdentifier() + " failed", input); @@ -120,26 +119,24 @@ public class WriteRunningTx extends AbstractWriteTx { @Override protected void editConfig(final DataContainerChild editStructure, final Optional defaultOperation) throws NetconfDocumentedException { - final String operation = "Edit running"; - invokeBlocking(operation, new Function>() { + invokeBlocking("Edit running", new Function>() { @Override public ListenableFuture apply(final NetconfBaseOps input) { - return perfomRequestWithTimeout(operation, defaultOperation.isPresent() - ? input.editConfigRunning(new NetconfRpcFutureCallback(operation, id), editStructure, defaultOperation.get(), - rollbackSupport) - : input.editConfigRunning(new NetconfRpcFutureCallback(operation, id), editStructure, - rollbackSupport)); + return defaultOperation.isPresent() + ? input.editConfigRunning(new NetconfRpcFutureCallback("Edit running", id), editStructure, defaultOperation.get(), + rollbackSupport) + : input.editConfigRunning(new NetconfRpcFutureCallback("Edit running", id), editStructure, + rollbackSupport); } }); } private void unlock() { - final String operation = "Unlocking running"; try { - invokeBlocking(operation, new Function>() { + invokeBlocking("Unlocking running", new Function>() { @Override public ListenableFuture apply(final NetconfBaseOps input) { - return perfomRequestWithTimeout(operation, input.unlockRunning(new NetconfRpcFutureCallback(operation, id))); + return input.unlockRunning(new NetconfRpcFutureCallback("Unlock running", id)); } }); } catch (final NetconfDocumentedException e) { diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacadeTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacadeTest.java index 2a6ba4301f..81e09708f3 100644 --- a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacadeTest.java +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacadeTest.java @@ -106,7 +106,7 @@ public class KeepaliveSalFacadeTest { doReturn(Futures.immediateCheckedFuture(result)).when(deviceRpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class)); final KeepaliveSalFacade keepaliveSalFacade = - new KeepaliveSalFacade(REMOTE_DEVICE_ID, underlyingSalFacade, executorServiceSpy, 1L); + new KeepaliveSalFacade(REMOTE_DEVICE_ID, underlyingSalFacade, executorServiceSpy, 1L, 1L); keepaliveSalFacade.setListener(listener); keepaliveSalFacade.onDeviceConnected(null, null, deviceRpc); @@ -133,7 +133,7 @@ public class KeepaliveSalFacadeTest { .when(deviceRpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class)); final KeepaliveSalFacade keepaliveSalFacade = - new KeepaliveSalFacade(REMOTE_DEVICE_ID, underlyingSalFacade, executorServiceSpy, 1L); + new KeepaliveSalFacade(REMOTE_DEVICE_ID, underlyingSalFacade, executorServiceSpy, 1L, 1L); keepaliveSalFacade.setListener(listener); keepaliveSalFacade.onDeviceConnected(null, null, deviceRpc); @@ -190,7 +190,7 @@ public class KeepaliveSalFacadeTest { .when(deviceRpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class)); final KeepaliveSalFacade keepaliveSalFacade = - new KeepaliveSalFacade(REMOTE_DEVICE_ID, underlyingSalFacade, executorServiceSpy, 100L); + new KeepaliveSalFacade(REMOTE_DEVICE_ID, underlyingSalFacade, executorServiceSpy, 100L, 1L); keepaliveSalFacade.setListener(listener); keepaliveSalFacade.onDeviceConnected(null, null, deviceRpc); diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBrokerTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBrokerTest.java index 1e15e115f3..c32f4fea33 100644 --- a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBrokerTest.java +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/NetconfDeviceDataBrokerTest.java @@ -103,7 +103,7 @@ public class NetconfDeviceDataBrokerTest { private NetconfDeviceDataBroker getDataBroker(String... caps) { NetconfSessionPreferences prefs = NetconfSessionPreferences.fromStrings(Arrays.asList(caps)); final RemoteDeviceId id = new RemoteDeviceId("device-1", InetSocketAddress.createUnresolved("localhost", 17830)); - return new NetconfDeviceDataBroker(id, schemaContext, rpcService, prefs, 1000); + return new NetconfDeviceDataBroker(id, schemaContext, rpcService, prefs); } } \ No newline at end of file diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java index 82fe4b23e7..ecb0eeb779 100644 --- a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java @@ -73,7 +73,7 @@ public class NetconfDeviceWriteOnlyTxTest { @Test public void testIgnoreNonVisibleData() { final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(SchemaContext.class)), - false, 60000L); + false); final MapNode emptyList = ImmutableNodes.mapNodeBuilder(NETCONF_FILTER_QNAME).build(); tx.merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(NETCONF_FILTER_QNAME)), emptyList); tx.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(NETCONF_FILTER_QNAME)), emptyList); @@ -84,7 +84,7 @@ public class NetconfDeviceWriteOnlyTxTest { @Test public void testDiscardChanges() { final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(SchemaContext.class)), - false, 60000L); + false); final CheckedFuture submitFuture = tx.submit(); try { submitFuture.checkedGet(); @@ -110,7 +110,7 @@ public class NetconfDeviceWriteOnlyTxTest { .doReturn(rpcErrorFuture).when(rpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class)); final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(SchemaContext.class)), - false, 60000L); + false); final CheckedFuture submitFuture = tx.submit(); try { @@ -129,7 +129,7 @@ public class NetconfDeviceWriteOnlyTxTest { .when(rpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class)); final WriteRunningTx tx = new WriteRunningTx(id, new NetconfBaseOps(rpc, NetconfMessageTransformer.BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS.getSchemaContext()), - false, 60000L); + false); try { tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId); } catch (final Exception e) { diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java index c005b5bf23..1e9c0fcd86 100644 --- a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java @@ -13,27 +13,17 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import com.google.common.base.Optional; -import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; import java.net.InetSocketAddress; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult; import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps; @@ -43,12 +33,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -@PrepareForTest({NetconfBaseOps.class}) -@RunWith(PowerMockRunner.class) public class ReadOnlyTxTest { private static final YangInstanceIdentifier path = YangInstanceIdentifier.create(); @@ -70,33 +55,11 @@ public class ReadOnlyTxTest { public void testRead() throws Exception { final NetconfBaseOps netconfOps = new NetconfBaseOps(rpc, mock(SchemaContext.class)); - final ReadOnlyTx readOnlyTx = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196)), 60000L); + final ReadOnlyTx readOnlyTx = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196))); readOnlyTx.read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create()); verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME)), any(NormalizedNode.class)); readOnlyTx.read(LogicalDatastoreType.OPERATIONAL, path); verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_QNAME)), any(NormalizedNode.class)); } - - @SuppressWarnings("unchecked") - @Test - public void testReadTimeout() throws Exception { - final ListenableFuture future = mock(ListenableFuture.class); - - Mockito.when(future.get(Mockito.anyLong(), any(TimeUnit.class))).then(new Answer() { - @Override - public DOMRpcResult answer(InvocationOnMock invocation) - throws Throwable { - throw new TimeoutException("Processing Timeout"); - } - }); - - final NetconfBaseOps netconfOps = PowerMockito.mock(NetconfBaseOps.class); - Mockito.when(netconfOps.getConfigRunning(any(FutureCallback.class), any(Optional.class))).thenReturn(future); - - - final ReadOnlyTx readOnlyTx = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196)), 100L); - Assert.assertNull("Read operation didn't correctly timeout", readOnlyTx.read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create())); - readOnlyTx.close(); - } } \ No newline at end of file diff --git a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/http/perf/RestPerfClient.java b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/http/perf/RestPerfClient.java index 5f6f490afc..6dc684780f 100644 --- a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/http/perf/RestPerfClient.java +++ b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/http/perf/RestPerfClient.java @@ -130,30 +130,37 @@ public class RestPerfClient { final ExecutorService executorService = Executors.newFixedThreadPool(threadAmount); LOG.info("Starting performance test"); + boolean allThreadsCompleted = true; final Stopwatch started = Stopwatch.createStarted(); try { final List> futures = executorService.invokeAll(callables, parameters.timeout, TimeUnit.MINUTES); for (int i = 0; i < futures.size(); i++) { Future future = futures.get(i); if (future.isCancelled()) { + allThreadsCompleted = false; LOG.info("{}. thread timed out.", i + 1); } else { try { future.get(); } catch (final ExecutionException e) { + allThreadsCompleted = false; LOG.info("{}. thread failed.", i + 1, e); } } } } catch (final InterruptedException e) { + allThreadsCompleted = false; LOG.warn("Unable to execute requests", e); } executorService.shutdownNow(); started.stop(); LOG.info("FINISHED. Execution time: {}", started); - LOG.info("Requests per second: {}", (parameters.editCount * 1000.0 / started.elapsed(TimeUnit.MILLISECONDS))); - + // If some threads failed or timed out, skip calculation of requests per second value + // and do not log it + if(allThreadsCompleted) { + LOG.info("Requests per second: {}", (parameters.editCount * 1000.0 / started.elapsed(TimeUnit.MILLISECONDS))); + } System.exit(0); } diff --git a/restconf/sal-rest-connector/pom.xml b/restconf/sal-rest-connector/pom.xml index 31b614766f..86c8a3dd67 100644 --- a/restconf/sal-rest-connector/pom.xml +++ b/restconf/sal-rest-connector/pom.xml @@ -124,7 +124,6 @@ net.java.dev.stax-utils stax-utils - 20070216 @@ -196,9 +195,9 @@ org.opendaylight.aaa.shiro.filters, org.opendaylight.aaa.shiro.realm, org.opendaylight.aaa.shiro.web.env, + org.opendaylight.aaa.filterchain.filters, org.apache.shiro.web.env - stax-utils /restconf diff --git a/restconf/sal-rest-connector/src/main/resources/WEB-INF/web.xml b/restconf/sal-rest-connector/src/main/resources/WEB-INF/web.xml index 4935729525..6b801d7321 100644 --- a/restconf/sal-rest-connector/src/main/resources/WEB-INF/web.xml +++ b/restconf/sal-rest-connector/src/main/resources/WEB-INF/web.xml @@ -32,6 +32,17 @@ /* + + DynamicFilterChain + org.opendaylight.aaa.filterchain.filters.CustomFilterAdapter + + + + DynamicFilterChain + /* + + + JAXRSRestconf /*