Add support for notifications for schemaless mountpoints.
SchemalessMessageTransformer treats notification's payload as anyxml
node. To conform to API transformer wraps this payload in container node
with notification type as node identifier.
Change-Id: I4aceee416c8d630fe7689738b34fda3778d9f10f
Signed-off-by: Jakub Morvay <jmorvay@cisco.com>
import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
import org.opendaylight.netconf.sal.connect.netconf.sal.SchemalessNetconfDeviceRpc;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseRpcSchemalessTransformer;
import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseSchema;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.SchemalessMessageTransformer;
+import org.opendaylight.netconf.sal.connect.util.MessageCounter;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
public class SchemalessNetconfDevice implements
private RemoteDeviceId id;
private RemoteDeviceHandler<NetconfSessionPreferences> salFacade;
+ private final SchemalessMessageTransformer messageTransformer;
+ private final BaseRpcSchemalessTransformer rpcTransformer;
public SchemalessNetconfDevice(final RemoteDeviceId id,
final RemoteDeviceHandler<NetconfSessionPreferences> salFacade) {
this.id = id;
this.salFacade = salFacade;
+ final MessageCounter counter = new MessageCounter();
+ rpcTransformer = new BaseRpcSchemalessTransformer(counter);
+ messageTransformer = new SchemalessMessageTransformer(counter);
}
@Override public void onRemoteSessionUp(final NetconfSessionPreferences remoteSessionCapabilities,
final NetconfDeviceCommunicator netconfDeviceCommunicator) {
-
final SchemalessNetconfDeviceRpc schemalessNetconfDeviceRpc = new SchemalessNetconfDeviceRpc(id,
- netconfDeviceCommunicator);
+ netconfDeviceCommunicator, rpcTransformer, messageTransformer);
salFacade.onDeviceConnected(BaseSchema.BASE_NETCONF_CTX.getSchemaContext(),
remoteSessionCapabilities, schemalessNetconfDeviceRpc);
}
@Override public void onNotification(final NetconfMessage notification) {
- // TODO support for notifications
+ salFacade.onNotification(messageTransformer.toNotification(notification));
}
}
import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseRpcSchemalessTransformer;
import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.SchemalessMessageTransformer;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
-import org.opendaylight.netconf.sal.connect.util.MessageCounter;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.common.RpcResult;
private final SchemalessMessageTransformer schemalessTransformer;
private final RemoteDeviceId deviceId;
- public SchemalessNetconfDeviceRpc(final RemoteDeviceId deviceId,
- final RemoteDeviceCommunicator<NetconfMessage> listener) {
+ public SchemalessNetconfDeviceRpc(RemoteDeviceId deviceId, final RemoteDeviceCommunicator<NetconfMessage> listener,
+ final BaseRpcSchemalessTransformer baseRpcTransformer,
+ final SchemalessMessageTransformer messageTransformer) {
this.deviceId = deviceId;
this.listener = listener;
- final MessageCounter counter = new MessageCounter();
- baseRpcTransformer = new BaseRpcSchemalessTransformer(counter);
- schemalessTransformer = new SchemalessMessageTransformer(counter);
+ this.baseRpcTransformer = baseRpcTransformer;
+ this.schemalessTransformer = messageTransformer;
}
@Nonnull
import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.IETF_NETCONF_NOTIFICATIONS;
import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_URI;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.stripNotification;
import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
import com.google.common.base.Function;
return new DefaultDOMRpcResult(normalizedNode);
}
- private static class NetconfDeviceNotification implements DOMNotification, DOMEvent {
+ static class NetconfDeviceNotification implements DOMNotification, DOMEvent {
private final ContainerNode content;
private final SchemaPath schemaPath;
private final Date eventTime;
*/
package org.opendaylight.netconf.sal.connect.netconf.schema.mapping;
+import java.util.Date;
+import java.util.Map;
import javax.xml.transform.dom.DOMSource;
+import org.opendaylight.controller.config.util.xml.MissingNameSpaceException;
+import org.opendaylight.controller.config.util.xml.XmlElement;
import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.netconf.sal.connect.util.MessageCounter;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
private static final YangInstanceIdentifier.NodeIdentifier REPLY_ID =
new YangInstanceIdentifier.NodeIdentifier(NetconfMessageTransformUtil.NETCONF_RPC_REPLY_QNAME);
+ // TODO maybe we should move this somewhere else as this
+ // might be used in applications using schemaless mountpoints
+ public static final YangInstanceIdentifier.NodeIdentifier SCHEMALESS_NOTIFICATION_PAYLOAD =
+ new YangInstanceIdentifier.NodeIdentifier(QName.create("schemaless-notification-payload"));
private final MessageCounter counter;
@Override
public DOMNotification toNotification(final NetconfMessage message) {
- //TODO add support for notifications
- throw new UnsupportedOperationException("Notifications not supported.");
+ final Map.Entry<Date, XmlElement> stripped = NetconfMessageTransformUtil.stripNotification(message);
+ final QName notificationNoRev;
+ try {
+ notificationNoRev =
+ QName.create(stripped.getValue().getNamespace(), stripped.getValue().getName()).withoutRevision();
+ } catch (final MissingNameSpaceException e) {
+ throw new IllegalArgumentException("Unable to parse notification " + message + ", cannot find namespace", e);
+ }
+
+ final AnyXmlNode notificationPayload = Builders.anyXmlBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(notificationNoRev))
+ .withValue(new DOMSource(stripped.getValue().getDomElement()))
+ .build();
+
+ final ContainerNode notificationBody = Builders.containerBuilder()
+ .withNodeIdentifier(SCHEMALESS_NOTIFICATION_PAYLOAD)
+ .withChild(notificationPayload)
+ .build();
+
+ return new NetconfMessageTransformer.NetconfDeviceNotification(notificationBody, stripped.getKey());
}
@Override
import org.opendaylight.controller.config.util.xml.XmlUtil;
import org.opendaylight.netconf.api.NetconfMessage;
import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseRpcSchemalessTransformer;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.SchemalessMessageTransformer;
+import org.opendaylight.netconf.sal.connect.util.MessageCounter;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
RpcResult<NetconfMessage> msg = null;
ListenableFuture<RpcResult<NetconfMessage>> future = Futures.immediateFuture(msg);
doReturn(future).when(listener).sendRequest(any(), any());
- deviceRpc = new SchemalessNetconfDeviceRpc(new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830)), listener);
+ final MessageCounter counter = new MessageCounter();
+ deviceRpc = new SchemalessNetconfDeviceRpc(
+ new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830)), listener,
+ new BaseRpcSchemalessTransformer(counter), new SchemalessMessageTransformer(counter));
}