import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
+import org.opendaylight.restconf.nb.rfc8040.rests.services.impl.MdsalRestconfServer;
import org.opendaylight.restconf.nb.rfc8040.rests.services.impl.RestconfDataStreamServiceImpl;
import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
import org.opendaylight.restconf.nb.rfc8040.streams.WebSocketInitializer;
@Reference final DOMMountPointService mountPointService,
@Reference final DOMNotificationService notificationService, @Reference final DOMRpcService rpcService,
@Reference final DOMSchemaService schemaService, @Reference final DatabindProvider databindProvider,
- final Configuration configuration) throws ServletException {
+ @Reference final MdsalRestconfServer server, final Configuration configuration) throws ServletException {
this(webServer, webContextSecurer, servletSupport, filterAdapterConfiguration, actionService, dataBroker,
- mountPointService, notificationService, rpcService, schemaService, databindProvider,
+ mountPointService, notificationService, rpcService, schemaService, databindProvider, server,
configuration.ping$_$executor$_$name$_$prefix(), configuration.max$_$thread$_$count(),
new StreamsConfiguration(configuration.maximum$_$fragment$_$length(), configuration.idle$_$timeout(),
configuration.heartbeat$_$interval(), configuration.use$_$sse()));
final DOMActionService actionService, final DOMDataBroker dataBroker,
final DOMMountPointService mountPointService, final DOMNotificationService notificationService,
final DOMRpcService rpcService, final DOMSchemaService schemaService,
- final DatabindProvider databindProvider,
+ final DatabindProvider databindProvider, final MdsalRestconfServer server,
final String pingNamePrefix, final int pingMaxThreadCount,
final StreamsConfiguration streamsConfiguration) throws ServletException {
final var scheduledThreadPool = new ScheduledThreadPoolWrapper(pingMaxThreadCount,
.addServlet(ServletDetails.builder()
.addUrlPattern("/*")
.servlet(servletSupport.createHttpServletBuilder(
- new RestconfApplication(databindProvider, mountPointService, dataBroker, rpcService, actionService,
- notificationService, schemaService, streamsConfiguration))
+ new RestconfApplication(databindProvider, server, mountPointService, dataBroker, rpcService,
+ actionService, notificationService, schemaService, streamsConfiguration))
.build())
.asyncSupported(true)
.build())
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
+import org.opendaylight.restconf.nb.rfc8040.rests.services.impl.MdsalRestconfServer;
import org.opendaylight.restconf.nb.rfc8040.rests.services.impl.RestconfDataServiceImpl;
import org.opendaylight.restconf.nb.rfc8040.rests.services.impl.RestconfImpl;
import org.opendaylight.restconf.nb.rfc8040.rests.services.impl.RestconfInvokeOperationsServiceImpl;
@Singleton
public class RestconfApplication extends AbstractRestconfApplication {
- private RestconfApplication(final DatabindProvider databindProvider, final DOMMountPointService mountPointService,
+ private RestconfApplication(final DatabindProvider databindProvider, final MdsalRestconfServer server,
+ final DOMMountPointService mountPointService,
final RestconfStreamsSubscriptionService streamSubscription, final DOMDataBroker dataBroker,
- final DOMRpcService rpcService, final DOMActionService actionService,
- final DOMNotificationService notificationService, final DOMSchemaService domSchemaService,
- final StreamsConfiguration configuration) {
+ final DOMActionService actionService, final DOMNotificationService notificationService,
+ final DOMSchemaService domSchemaService, final StreamsConfiguration configuration) {
super(databindProvider, List.of(
streamSubscription,
- new RestconfDataServiceImpl(databindProvider, dataBroker, mountPointService, streamSubscription,
- actionService, configuration),
- new RestconfInvokeOperationsServiceImpl(databindProvider, rpcService, mountPointService, configuration),
- new RestconfOperationsServiceImpl(databindProvider, mountPointService),
+ new RestconfDataServiceImpl(databindProvider, server, dataBroker, streamSubscription, actionService,
+ configuration),
+ new RestconfInvokeOperationsServiceImpl(databindProvider, server, mountPointService, configuration),
+ new RestconfOperationsServiceImpl(databindProvider, server),
new RestconfSchemaServiceImpl(domSchemaService, mountPointService),
new RestconfImpl(databindProvider)));
}
@Inject
- public RestconfApplication(final DatabindProvider databindProvider, final DOMMountPointService mountPointService,
- final DOMDataBroker dataBroker, final DOMRpcService rpcService, final DOMActionService actionService,
+ public RestconfApplication(final DatabindProvider databindProvider, final MdsalRestconfServer server,
+ final DOMMountPointService mountPointService, final DOMDataBroker dataBroker,
+ final DOMRpcService rpcService, final DOMActionService actionService,
final DOMNotificationService notificationService, final DOMSchemaService domSchemaService,
final StreamsConfiguration configuration) {
- this(databindProvider, mountPointService,
+ this(databindProvider, server, mountPointService,
new RestconfStreamsSubscriptionServiceImpl(dataBroker, notificationService, databindProvider,
configuration),
- dataBroker, rpcService, actionService, notificationService, domSchemaService, configuration);
+ dataBroker, actionService, notificationService, domSchemaService, configuration);
}
}
import org.opendaylight.mdsal.dom.api.DOMNotificationService;
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants;
import org.opendaylight.restconf.nb.rfc8040.streams.listeners.DeviceNotificationListenerAdaptor;
* </pre>
*/
// FIXME: this really should be a normal RPC implementation
- static DOMRpcResult createDataChangeNotifiStream(final ListenersBroker listenersBroker, final ContainerNode input,
+ static ContainerNode createDataChangeNotifiStream(final ListenersBroker listenersBroker, final ContainerNode input,
final EffectiveModelContext refSchemaCtx) {
// parsing out of container with settings and path
final YangInstanceIdentifier path = preparePath(input);
listenersBroker.registerDataChangeListener(path, streamName, outputType);
// building of output
- return new DefaultDOMRpcResult(Builders.containerBuilder()
+ return Builders.containerBuilder()
.withNodeIdentifier(SAL_REMOTE_OUTPUT_NODEID)
.withChild(ImmutableNodes.leafNode(STREAM_NAME_NODEID, streamName))
- .build());
+ .build();
}
/**
* @param mountPointService dom mount point service
* @return {@link DOMRpcResult} - Output of RPC - example in JSON
*/
- static DOMRpcResult createDeviceNotificationListener(final String baseUrl, final ContainerNode input,
+ // FIXME: this should be an RPC invocation
+ static ContainerNode createDeviceNotificationListener(final String baseUrl, final ContainerNode input,
final SubscribeToStreamUtil streamUtil, final DOMMountPointService mountPointService) {
// parsing out of container with settings and path
// FIXME: ugly cast
mountPointService, mountPoint.getIdentifier());
notificationListenerAdapter.listen(mountNotifService, notificationPaths);
- // building of output
- return new DefaultDOMRpcResult(Builders.containerBuilder()
+ return Builders.containerBuilder()
.withNodeIdentifier(new NodeIdentifier(SubscribeDeviceNotificationOutput.QNAME))
- .withChild(ImmutableNodes.leafNode(DEVICE_NOTIFICATION_STREAM_PATH, baseUrl + deviceName
- + "?" + RestconfStreamsConstants.NOTIFICATION_TYPE + "=" + RestconfStreamsConstants.DEVICE))
- .build());
+ .withChild(ImmutableNodes.leafNode(DEVICE_NOTIFICATION_STREAM_PATH, baseUrl + deviceName + "?"
+ + RestconfStreamsConstants.NOTIFICATION_TYPE + "=" + RestconfStreamsConstants.DEVICE))
+ .build();
}
/**
--- /dev/null
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.restconf.nb.rfc8040.rests.services.impl;
+
+import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMMountPoint;
+import org.opendaylight.mdsal.dom.api.DOMMountPointService;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
+import org.opendaylight.restconf.nb.rfc8040.legacy.InstanceIdentifierContext;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
+import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A RESTCONF server implemented on top of MD-SAL.
+ */
+// FIXME: factor out the 'RestconfServer' interface once we're ready
+// FIXME: this should live in 'org.opendaylight.restconf.server.mdsal' package
+@Singleton
+@Component(service = MdsalRestconfServer.class)
+public final class MdsalRestconfServer {
+ private static final Logger LOG = LoggerFactory.getLogger(MdsalRestconfServer.class);
+ private static final VarHandle LOCAL_STRATEGY;
+
+ static {
+ try {
+ LOCAL_STRATEGY = MethodHandles.lookup()
+ .findVarHandle(MdsalRestconfServer.class, "localStrategy", RestconfStrategy.class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ private final @NonNull DOMMountPointService mountPointService;
+ private final @NonNull DOMDataBroker dataBroker;
+ private final @Nullable DOMRpcService rpcService;
+
+ @SuppressWarnings("unused")
+ private volatile RestconfStrategy localStrategy;
+
+ @Inject
+ @Activate
+ public MdsalRestconfServer(@Reference final DOMDataBroker dataBroker, @Reference final DOMRpcService rpcService,
+ @Reference final DOMMountPointService mountPointService) {
+ this.dataBroker = requireNonNull(dataBroker);
+ this.rpcService = requireNonNull(rpcService);
+ this.mountPointService = requireNonNull(mountPointService);
+ }
+
+ @NonNull InstanceIdentifierContext bindRequestPath(final DatabindContext databind, final String identifier) {
+ // FIXME: go through ApiPath first. That part should eventually live in callers
+ // FIXME: DatabindContext looks like it should be internal
+ return verifyNotNull(ParserIdentifier.toInstanceIdentifier(requireNonNull(identifier), databind.modelContext(),
+ mountPointService));
+ }
+
+ @SuppressWarnings("static-method")
+ @NonNull InstanceIdentifierContext bindRequestRoot(final DatabindContext databind) {
+ return InstanceIdentifierContext.ofLocalRoot(databind.modelContext());
+ }
+
+ @VisibleForTesting
+ @NonNull RestconfStrategy getRestconfStrategy(final EffectiveModelContext modelContext,
+ final @Nullable DOMMountPoint mountPoint) {
+ if (mountPoint == null) {
+ return localStrategy(modelContext);
+ }
+
+ final var ret = RestconfStrategy.forMountPoint(modelContext, mountPoint);
+ if (ret == null) {
+ final var mountId = mountPoint.getIdentifier();
+ LOG.warn("Mount point {} does not expose a suitable access interface", mountId);
+ throw new RestconfDocumentedException("Could not find a supported access interface in mount point "
+ + mountId);
+ }
+ return ret;
+ }
+
+ private @NonNull RestconfStrategy localStrategy(final EffectiveModelContext modelContext) {
+ final var local = (RestconfStrategy) LOCAL_STRATEGY.getAcquire(this);
+ if (local != null && modelContext.equals(local.modelContext())) {
+ return local;
+ }
+
+ final var created = new MdsalRestconfStrategy(modelContext, dataBroker, rpcService);
+ LOCAL_STRATEGY.setRelease(this, created);
+ return created;
+ }
+}
this.emptyBody = requireNonNull(emptyBody);
}
- /**
- * Return the content for a particular {@link EffectiveModelContext}.
- *
- * @param context Context to use
- * @return Content of HTTP GET operation as a String
- */
- public final @NonNull String bodyFor(final EffectiveModelContext context) {
- if (isEmptyContext(context)) {
- // No modules, or defensive return empty content
- return emptyBody;
- }
-
- final var moduleRpcs = getModuleRpcs(context, context.getModuleStatements());
- return moduleRpcs.isEmpty() ? emptyBody : createBody(moduleRpcs);
- }
-
/**
* Return content with RPCs and actions for a particular {@link Inference}.
*
import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
import java.net.URI;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import javax.ws.rs.Consumes;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteOperations;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
-import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.patch.PatchContext;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
import org.opendaylight.restconf.nb.rfc8040.MediaTypes;
+import org.opendaylight.restconf.nb.rfc8040.ReadDataParams;
import org.opendaylight.restconf.nb.rfc8040.databind.ChildBody;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
import org.opendaylight.restconf.nb.rfc8040.databind.JsonChildBody;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.nb.rfc8040.monitoring.RestconfStateStreams;
import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants;
import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
import org.opendaylight.restconf.nb.rfc8040.streams.listeners.ListenersBroker;
import org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationListenerAdapter;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.IdentifierCodec;
-import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType;
import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.common.ErrorTag;
public final class RestconfDataServiceImpl {
private static final Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class);
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss");
- private static final VarHandle LOCAL_STRATEGY;
-
- static {
- try {
- LOCAL_STRATEGY = MethodHandles.lookup()
- .findVarHandle(RestconfDataServiceImpl.class, "localStrategy", RestconfStrategy.class);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
private final RestconfStreamsSubscriptionService delegRestconfSubscrService;
private final DatabindProvider databindProvider;
- private final DOMMountPointService mountPointService;
private final SubscribeToStreamUtil streamUtils;
private final DOMActionService actionService;
+ private final MdsalRestconfServer server;
+ @Deprecated(forRemoval = true)
private final DOMDataBroker dataBroker;
private final ListenersBroker listenersBroker = ListenersBroker.getInstance();
- @SuppressWarnings("unused")
- private volatile RestconfStrategy localStrategy;
-
- public RestconfDataServiceImpl(final DatabindProvider databindProvider,
- final DOMDataBroker dataBroker, final DOMMountPointService mountPointService,
- final RestconfStreamsSubscriptionService delegRestconfSubscrService,
+ public RestconfDataServiceImpl(final DatabindProvider databindProvider, final MdsalRestconfServer server,
+ final DOMDataBroker dataBroker, final RestconfStreamsSubscriptionService delegRestconfSubscrService,
final DOMActionService actionService, final StreamsConfiguration configuration) {
this.databindProvider = requireNonNull(databindProvider);
+ this.server = requireNonNull(server);
this.dataBroker = requireNonNull(dataBroker);
- this.mountPointService = requireNonNull(mountPointService);
this.delegRestconfSubscrService = requireNonNull(delegRestconfSubscrService);
this.actionService = requireNonNull(actionService);
streamUtils = configuration.useSSE() ? SubscribeToStreamUtil.serverSentEvents()
MediaType.TEXT_XML
})
public Response readData(@Context final UriInfo uriInfo) {
- return readData(null, uriInfo);
+ final var readParams = QueryParams.newReadDataParams(uriInfo);
+ return readData(server.bindRequestRoot(databindProvider.currentContext()), readParams).getValue();
}
/**
public Response readData(@Encoded @PathParam("identifier") final String identifier,
@Context final UriInfo uriInfo) {
final var readParams = QueryParams.newReadDataParams(uriInfo);
- final var schemaContextRef = databindProvider.currentContext().modelContext();
- // FIXME: go through
- final var instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier, schemaContextRef,
- mountPointService);
- final var mountPoint = instanceIdentifier.getMountPoint();
+ final var databind = databindProvider.currentContext();
+ final var schemaContextRef = databind.modelContext();
+ final var reqPath = server.bindRequestPath(databind, identifier);
+ final var mountPoint = reqPath.getMountPoint();
// FIXME: this looks quite crazy, why do we even have it?
if (mountPoint == null && identifier != null && identifier.contains(STREAMS_PATH)
createAllYangNotificationStreams(schemaContextRef, uriInfo);
}
- final var queryParams = QueryParams.newQueryParameters(readParams, instanceIdentifier);
- final var fieldPaths = queryParams.fieldPaths();
- // FIXME:the model context should be coming from instanceIdentifier!
- final var strategy = getRestconfStrategy(schemaContextRef, mountPoint);
- final NormalizedNode node;
- if (fieldPaths != null && !fieldPaths.isEmpty()) {
- node = strategy.readData(readParams.content(), instanceIdentifier.getInstanceIdentifier(),
- readParams.withDefaults(), fieldPaths);
- } else {
- node = strategy.readData(readParams.content(), instanceIdentifier.getInstanceIdentifier(),
- readParams.withDefaults());
- }
+ final var nodeAndResponse = readData(reqPath, readParams);
// FIXME: this is utter craziness, refactor it properly!
if (identifier != null && identifier.contains(STREAM_PATH) && identifier.contains(STREAM_ACCESS_PATH_PART)
&& identifier.contains(STREAM_LOCATION_PATH_PART)) {
- final String value = (String) node.body();
+ final String value = (String) nodeAndResponse.getKey().body();
final String streamName = value.substring(value.indexOf(NOTIFICATION_STREAM + '/'));
delegRestconfSubscrService.subscribeToStream(streamName, uriInfo);
}
+
+ return nodeAndResponse.getValue();
+ }
+
+ private Entry<NormalizedNode, Response> readData(final InstanceIdentifierContext reqPath,
+ final ReadDataParams readParams) {
+ final var queryParams = QueryParams.newQueryParameters(readParams, reqPath);
+ final var fieldPaths = queryParams.fieldPaths();
+ final var strategy = server.getRestconfStrategy(reqPath.getSchemaContext(), reqPath.getMountPoint());
+ final NormalizedNode node;
+ if (fieldPaths != null && !fieldPaths.isEmpty()) {
+ node = strategy.readData(readParams.content(), reqPath.getInstanceIdentifier(),
+ readParams.withDefaults(), fieldPaths);
+ } else {
+ node = strategy.readData(readParams.content(), reqPath.getInstanceIdentifier(),
+ readParams.withDefaults());
+ }
if (node == null) {
throw new RestconfDocumentedException(
"Request could not be completed because the relevant data model content does not exist",
ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
}
- return switch (readParams.content()) {
+ return Map.entry(node, switch (readParams.content()) {
case ALL, CONFIG -> {
final QName type = node.name().getNodeType();
yield Response.status(Status.OK)
- .entity(new NormalizedNodePayload(instanceIdentifier.inference(), node, queryParams))
+ .entity(new NormalizedNodePayload(reqPath.inference(), node, queryParams))
.header("ETag", '"' + type.getModule().getRevision().map(Revision::toString).orElse(null) + "-"
+ type.getLocalName() + '"')
.header("Last-Modified", FORMATTER.format(LocalDateTime.now(Clock.systemUTC())))
.build();
}
case NONCONFIG -> Response.status(Status.OK)
- .entity(new NormalizedNodePayload(instanceIdentifier.inference(), node, queryParams))
+ .entity(new NormalizedNodePayload(reqPath.inference(), node, queryParams))
.build();
- };
+ });
}
private void createAllYangNotificationStreams(final EffectiveModelContext schemaContext, final UriInfo uriInfo) {
}
private Response putData(final @Nullable String identifier, final UriInfo uriInfo, final ResourceBody body) {
- final var localModel = databindProvider.currentContext().modelContext();
- final var context = ParserIdentifier.toInstanceIdentifier(identifier, localModel, mountPointService);
- final var insert = QueryParams.parseInsert(context.getSchemaContext(), uriInfo);
- final var req = bindResourceRequest(context, body);
+ final var reqPath = server.bindRequestPath(databindProvider.currentContext(), identifier);
+ final var insert = QueryParams.parseInsert(reqPath.getSchemaContext(), uriInfo);
+ final var req = bindResourceRequest(reqPath, body);
return switch (
req.strategy().putData(req.path(), req.data(), insert)) {
})
public Response postDataJSON(@Encoded @PathParam("identifier") final String identifier, final InputStream body,
@Context final UriInfo uriInfo) {
- final var instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
- databindProvider.currentContext().modelContext(), mountPointService);
- if (instanceIdentifier.getSchemaNode() instanceof ActionDefinition) {
+ final var reqPath = server.bindRequestPath(databindProvider.currentContext(), identifier);
+ if (reqPath.getSchemaNode() instanceof ActionDefinition) {
try (var jsonBody = new JsonOperationInputBody(body)) {
- return invokeAction(instanceIdentifier, jsonBody);
+ return invokeAction(reqPath, jsonBody);
}
}
try (var jsonBody = new JsonChildBody(body)) {
- return postData(instanceIdentifier.inference(), instanceIdentifier.getInstanceIdentifier(), jsonBody,
- uriInfo, instanceIdentifier.getMountPoint());
+ return postData(reqPath.inference(), reqPath.getInstanceIdentifier(), jsonBody, uriInfo,
+ reqPath.getMountPoint());
}
}
})
public Response postDataXML(@Encoded @PathParam("identifier") final String identifier, final InputStream body,
@Context final UriInfo uriInfo) {
- final var iid = ParserIdentifier.toInstanceIdentifier(identifier,
- databindProvider.currentContext().modelContext(), mountPointService);
- if (iid.getSchemaNode() instanceof ActionDefinition) {
+ final var reqPath = server.bindRequestPath(databindProvider.currentContext(), identifier);
+ if (reqPath.getSchemaNode() instanceof ActionDefinition) {
try (var xmlBody = new XmlOperationInputBody(body)) {
- return invokeAction(iid, xmlBody);
+ return invokeAction(reqPath, xmlBody);
}
}
try (var xmlBody = new XmlChildBody(body)) {
- return postData(iid.inference(), iid.getInstanceIdentifier(), xmlBody, uriInfo, iid.getMountPoint());
+ return postData(reqPath.inference(), reqPath.getInstanceIdentifier(), xmlBody, uriInfo,
+ reqPath.getMountPoint());
}
}
final UriInfo uriInfo, final @Nullable DOMMountPoint mountPoint) {
final var modelContext = inference.getEffectiveModelContext();
final var insert = QueryParams.parseInsert(modelContext, uriInfo);
- final var strategy = getRestconfStrategy(modelContext, mountPoint);
+ final var strategy = server.getRestconfStrategy(modelContext, mountPoint);
var path = parentPath;
final var payload = body.toPayload(path, inference);
final var data = payload.body();
@Path("/data/{identifier:.+}")
public void deleteData(@Encoded @PathParam("identifier") final String identifier,
@Suspended final AsyncResponse ar) {
- final var instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
- databindProvider.currentContext().modelContext(), mountPointService);
- final var strategy = getRestconfStrategy(instanceIdentifier.getSchemaContext(),
- instanceIdentifier.getMountPoint());
+ final var reqPath = server.bindRequestPath(databindProvider.currentContext(), identifier);
+ final var strategy = server.getRestconfStrategy(reqPath.getSchemaContext(), reqPath.getMountPoint());
- Futures.addCallback(strategy.delete(instanceIdentifier.getInstanceIdentifier()), new FutureCallback<>() {
+ Futures.addCallback(strategy.delete(reqPath.getInstanceIdentifier()), new FutureCallback<>() {
@Override
public void onSuccess(final Empty result) {
ar.resume(Response.noContent().build());
})
public void plainPatchDataXML(final InputStream body, @Suspended final AsyncResponse ar) {
try (var xmlBody = new XmlResourceBody(body)) {
- plainPatchData(null, xmlBody, ar);
+ plainPatchData(xmlBody, ar);
}
}
})
public void plainPatchDataJSON(final InputStream body, @Suspended final AsyncResponse ar) {
try (var jsonBody = new JsonResourceBody(body)) {
- plainPatchData(null, jsonBody, ar);
+ plainPatchData(jsonBody, ar);
}
}
}
}
+ /**
+ * Partially modify the target data resource, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.6.1">RFC8040, section 4.6.1</a>.
+ *
+ * @param body data node for put to config DS
+ * @param ar {@link AsyncResponse} which needs to be completed
+ */
+ private void plainPatchData(final ResourceBody body, final AsyncResponse ar) {
+ plainPatchData(server.bindRequestRoot(databindProvider.currentContext()), body, ar);
+ }
+
/**
* Partially modify the target data resource, as defined in
* <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.6.1">RFC8040, section 4.6.1</a>.
* @param body data node for put to config DS
* @param ar {@link AsyncResponse} which needs to be completed
*/
- private void plainPatchData(final @Nullable String identifier, final ResourceBody body, final AsyncResponse ar) {
- final var req = bindResourceRequest(
- ParserIdentifier.toInstanceIdentifier(identifier, databindProvider.currentContext().modelContext(),
- mountPointService),
- body);
+ private void plainPatchData(final String identifier, final ResourceBody body, final AsyncResponse ar) {
+ plainPatchData(server.bindRequestPath(databindProvider.currentContext(), identifier), body, ar);
+ }
+
+ /**
+ * Partially modify the target data resource, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.6.1">RFC8040, section 4.6.1</a>.
+ *
+ * @param reqPath path to target
+ * @param body data node for put to config DS
+ * @param ar {@link AsyncResponse} which needs to be completed
+ */
+ private void plainPatchData(final InstanceIdentifierContext reqPath, final ResourceBody body,
+ final AsyncResponse ar) {
+ final var req = bindResourceRequest(reqPath, body);
final var future = req.strategy().merge(req.path(), req.data());
Futures.addCallback(future, new FutureCallback<>() {
}, MoreExecutors.directExecutor());
}
- private @NonNull ResourceRequest bindResourceRequest(final InstanceIdentifierContext context,
+ private @NonNull ResourceRequest bindResourceRequest(final InstanceIdentifierContext reqPath,
final ResourceBody body) {
- final var inference = context.inference();
- final var path = context.getInstanceIdentifier();
- final var data = body.toNormalizedNode(path, inference, context.getSchemaNode());
+ final var inference = reqPath.inference();
+ final var path = reqPath.getInstanceIdentifier();
+ final var data = body.toNormalizedNode(path, inference, reqPath.getSchemaNode());
- return new ResourceRequest(getRestconfStrategy(inference.getEffectiveModelContext(), context.getMountPoint()),
+ return new ResourceRequest(
+ server.getRestconfStrategy(inference.getEffectiveModelContext(), reqPath.getMountPoint()),
path, data);
}
}
private PatchStatusContext yangPatchData(final String identifier, final @NonNull PatchBody body) {
- final var iid = ParserIdentifier.toInstanceIdentifier(requireNonNull(identifier),
- databindProvider.currentContext().modelContext(), mountPointService);
- final var context = iid.getSchemaContext();
- return yangPatchData(context, parsePatchBody(context, iid.getInstanceIdentifier(), body), iid.getMountPoint());
+ final var reqPath = server.bindRequestPath(databindProvider.currentContext(), identifier);
+ final var modelContext = reqPath.getSchemaContext();
+ return yangPatchData(modelContext, parsePatchBody(modelContext, reqPath.getInstanceIdentifier(), body),
+ reqPath.getMountPoint());
}
@VisibleForTesting
@NonNull PatchStatusContext yangPatchData(final @NonNull EffectiveModelContext modelContext,
final @NonNull PatchContext patch, final @Nullable DOMMountPoint mountPoint) {
- return getRestconfStrategy(modelContext, mountPoint).patchData(patch);
+ return server.getRestconfStrategy(modelContext, mountPoint).patchData(patch);
}
private static @NonNull PatchContext parsePatchBody(final @NonNull EffectiveModelContext context,
}
}
- @VisibleForTesting
- @NonNull RestconfStrategy getRestconfStrategy(final EffectiveModelContext modelContext,
- final @Nullable DOMMountPoint mountPoint) {
- if (mountPoint == null) {
- return localStrategy(modelContext);
- }
-
- final var ret = RestconfStrategy.forMountPoint(modelContext, mountPoint);
- if (ret == null) {
- final var mountId = mountPoint.getIdentifier();
- LOG.warn("Mount point {} does not expose a suitable access interface", mountId);
- throw new RestconfDocumentedException("Could not find a supported access interface in mount point "
- + mountId);
- }
- return ret;
- }
-
- private @NonNull RestconfStrategy localStrategy(final EffectiveModelContext modelContext) {
- final var local = (RestconfStrategy) LOCAL_STRATEGY.getAcquire(this);
- if (local != null && modelContext.equals(local.modelContext())) {
- return local;
- }
-
- final var created = new MdsalRestconfStrategy(modelContext, dataBroker);
- LOCAL_STRATEGY.setRelease(this, created);
- return created;
- }
-
/**
* Invoke Action operation.
*
* @param payload {@link NormalizedNodePayload} - the body of the operation
* @return {@link NormalizedNodePayload} wrapped in {@link Response}
*/
- private Response invokeAction(final InstanceIdentifierContext context, final OperationInputBody body) {
- final var yangIIdContext = context.getInstanceIdentifier();
+ private Response invokeAction(final InstanceIdentifierContext reqPath, final OperationInputBody body) {
+ final var yangIIdContext = reqPath.getInstanceIdentifier();
final ContainerNode input;
try {
- input = body.toContainerNode(context.inference());
+ input = body.toContainerNode(reqPath.inference());
} catch (IOException e) {
LOG.debug("Error reading input", e);
throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
ErrorTag.MALFORMED_MESSAGE, e);
}
- final var mountPoint = context.getMountPoint();
- final var inference = context.inference();
+ final var mountPoint = reqPath.getMountPoint();
+ final var inference = reqPath.inference();
final var schemaPath = inference.toSchemaInferenceStack().toSchemaNodeIdentifier();
final var response = mountPoint != null ? invokeAction(input, schemaPath, yangIIdContext, mountPoint)
: invokeAction(input, schemaPath, yangIIdContext, actionService);
import static java.util.Objects.requireNonNull;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.io.InputStream;
-import java.util.List;
+import java.util.Optional;
import javax.ws.rs.Consumes;
import javax.ws.rs.Encoded;
import javax.ws.rs.POST;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.mdsal.dom.api.DOMRpcException;
-import org.opendaylight.mdsal.dom.api.DOMRpcResult;
-import org.opendaylight.mdsal.dom.api.DOMRpcService;
-import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.common.errors.RestconfFuture;
import org.opendaylight.restconf.nb.rfc8040.MediaTypes;
+import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
import org.opendaylight.restconf.nb.rfc8040.databind.JsonOperationInputBody;
import org.opendaylight.restconf.nb.rfc8040.databind.OperationInputBody;
import org.opendaylight.restconf.nb.rfc8040.databind.XmlOperationInputBody;
+import org.opendaylight.restconf.nb.rfc8040.legacy.InstanceIdentifierContext;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
-import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
import org.opendaylight.yang.gen.v1.urn.opendaylight.device.notification.rev221106.SubscribeDeviceNotification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.CreateDataChangeEventSubscription;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(RestconfInvokeOperationsServiceImpl.class);
private final DatabindProvider databindProvider;
- private final DOMRpcService rpcService;
+ private final MdsalRestconfServer server;
+ @Deprecated(forRemoval = true)
private final DOMMountPointService mountPointService;
private final SubscribeToStreamUtil streamUtils;
- public RestconfInvokeOperationsServiceImpl(final DatabindProvider databindProvider, final DOMRpcService rpcService,
- final DOMMountPointService mountPointService, final StreamsConfiguration configuration) {
+ public RestconfInvokeOperationsServiceImpl(final DatabindProvider databindProvider,
+ final MdsalRestconfServer server, final DOMMountPointService mountPointService,
+ final StreamsConfiguration configuration) {
this.databindProvider = requireNonNull(databindProvider);
- this.rpcService = requireNonNull(rpcService);
+ this.server = requireNonNull(server);
this.mountPointService = requireNonNull(mountPointService);
streamUtils = configuration.useSSE() ? SubscribeToStreamUtil.serverSentEvents()
: SubscribeToStreamUtil.webSockets();
private void invokeRpc(final String identifier, final UriInfo uriInfo, final AsyncResponse ar,
final OperationInputBody body) {
- final var dataBind = databindProvider.currentContext();
- final var schemaContext = dataBind.modelContext();
- final var context = ParserIdentifier.toInstanceIdentifier(identifier, schemaContext, mountPointService);
+ final var databind = databindProvider.currentContext();
+ final var reqPath = server.bindRequestPath(databind, identifier);
final ContainerNode input;
try {
- input = body.toContainerNode(context.inference());
+ input = body.toContainerNode(reqPath.inference());
} catch (IOException e) {
LOG.debug("Error reading input", e);
throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
ErrorTag.MALFORMED_MESSAGE, e);
}
- final var rpcName = context.getSchemaNode().getQName();
- final ListenableFuture<? extends DOMRpcResult> future;
- final var mountPoint = context.getMountPoint();
- if (mountPoint == null) {
- if (CreateDataChangeEventSubscription.QNAME.equals(rpcName)) {
- future = Futures.immediateFuture(CreateStreamUtil.createDataChangeNotifiStream(
- streamUtils.listenersBroker(), input, schemaContext));
- } else if (SubscribeDeviceNotification.QNAME.equals(rpcName)) {
- final String baseUrl = streamUtils.prepareUriByStreamName(uriInfo, "").toString();
- future = Futures.immediateFuture(CreateStreamUtil.createDeviceNotificationListener(baseUrl, input,
- streamUtils, mountPointService));
- } else {
- future = invokeRpc(input, rpcName, rpcService);
- }
- } else {
- future = invokeRpc(input, rpcName, mountPoint);
- }
-
- Futures.addCallback(future, new FutureCallback<DOMRpcResult>() {
+ Futures.addCallback(hackInvokeRpc(databind, reqPath, uriInfo, input), new FutureCallback<>() {
@Override
- public void onSuccess(final DOMRpcResult response) {
- final var errors = response.errors();
- if (!errors.isEmpty()) {
- LOG.debug("RpcError message {}", response.errors());
- ar.resume(new RestconfDocumentedException("RPCerror message ", null, response.errors()));
- return;
- }
-
- final ContainerNode resultData = response.value();
- if (resultData == null || resultData.isEmpty()) {
- ar.resume(Response.noContent().build());
- } else {
- ar.resume(Response.ok().entity(new NormalizedNodePayload(context.inference(), resultData)).build());
+ public void onSuccess(final Optional<ContainerNode> result) {
+ if (result.isPresent()) {
+ final var output = result.orElseThrow();
+ if (!output.isEmpty()) {
+ ar.resume(Response.ok().entity(new NormalizedNodePayload(reqPath.inference(), output)).build());
+ return;
+ }
}
+ ar.resume(Response.noContent().build());
}
@Override
}, MoreExecutors.directExecutor());
}
- /**
- * Invoking rpc via mount point.
- *
- * @param mountPoint mount point
- * @param data input data
- * @param rpc RPC type
- * @return {@link DOMRpcResult}
- */
- @VisibleForTesting
- static ListenableFuture<? extends DOMRpcResult> invokeRpc(final ContainerNode data, final QName rpc,
- final DOMMountPoint mountPoint) {
- return invokeRpc(data, rpc, mountPoint.getService(DOMRpcService.class).orElseThrow(() -> {
- final String errmsg = "RPC service is missing.";
- LOG.debug(errmsg);
- return new RestconfDocumentedException(errmsg);
- }));
- }
-
- /**
- * Invoke rpc.
- *
- * @param input input data
- * @param rpc RPC type
- * @param rpcService rpc service to invoke rpc
- * @return {@link DOMRpcResult}
- */
- @VisibleForTesting
- static ListenableFuture<? extends DOMRpcResult> invokeRpc(final ContainerNode input, final QName rpc,
- final DOMRpcService rpcService) {
- return Futures.catching(rpcService.invokeRpc(rpc, nonnullInput(rpc, input)), DOMRpcException.class,
- cause -> new DefaultDOMRpcResult(List.of(RpcResultBuilder.newError(ErrorType.RPC, ErrorTag.OPERATION_FAILED,
- cause.getMessage()))),
- MoreExecutors.directExecutor());
- }
+ private RestconfFuture<Optional<ContainerNode>> hackInvokeRpc(final DatabindContext localDatabind,
+ final InstanceIdentifierContext reqPath, final UriInfo uriInfo, final ContainerNode input) {
+ // RPC type
+ final var type = reqPath.getSchemaNode().getQName();
+ final var mountPoint = reqPath.getMountPoint();
+ if (mountPoint == null) {
+ // Hacked-up integration of streams
+ if (CreateDataChangeEventSubscription.QNAME.equals(type)) {
+ return RestconfFuture.of(Optional.of(CreateStreamUtil.createDataChangeNotifiStream(
+ streamUtils.listenersBroker(), input, localDatabind.modelContext())));
+ } else if (SubscribeDeviceNotification.QNAME.equals(type)) {
+ final var baseUrl = streamUtils.prepareUriByStreamName(uriInfo, "").toString();
+ return RestconfFuture.of(Optional.of(CreateStreamUtil.createDeviceNotificationListener(baseUrl, input,
+ streamUtils, mountPointService)));
+ }
+ }
- private static @NonNull ContainerNode nonnullInput(final QName type, final ContainerNode input) {
- return input != null ? input
- : ImmutableNodes.containerNode(YangConstants.operationInputQName(type.getModule()));
+ return server.getRestconfStrategy(reqPath.getSchemaContext(), mountPoint).invokeRpc(type, input);
}
}
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
-import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.restconf.nb.rfc8040.MediaTypes;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
-import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
/**
@Path("/")
public final class RestconfOperationsServiceImpl {
private final DatabindProvider databindProvider;
- private final DOMMountPointService mountPointService;
+ private final MdsalRestconfServer server;
/**
* Set {@link DatabindProvider} for getting actual {@link EffectiveModelContext}.
*
* @param databindProvider a {@link DatabindProvider}
- * @param mountPointService a {@link DOMMountPointService}
+ * @param server a {@link MdsalRestconfServer}
*/
- public RestconfOperationsServiceImpl(final DatabindProvider databindProvider,
- final DOMMountPointService mountPointService) {
+ public RestconfOperationsServiceImpl(final DatabindProvider databindProvider, final MdsalRestconfServer server) {
this.databindProvider = requireNonNull(databindProvider);
- this.mountPointService = requireNonNull(mountPointService);
+ this.server = requireNonNull(server);
}
/**
@Path("/operations")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
public String getOperationsJSON() {
- return OperationsContent.JSON.bodyFor(databindProvider.currentContext().modelContext());
+ return OperationsContent.JSON.bodyFor(
+ server.bindRequestRoot(databindProvider.currentContext()).inference());
}
/**
@Path("/operations/{identifier:.+}")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
public String getOperationJSON(@PathParam("identifier") final String identifier) {
- return OperationsContent.JSON.bodyFor(ParserIdentifier.toInstanceIdentifier(identifier,
- databindProvider.currentContext().modelContext(), mountPointService).inference());
+ return OperationsContent.JSON.bodyFor(
+ server.bindRequestPath(databindProvider.currentContext(), identifier).inference());
}
/**
@Path("/operations")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
public String getOperationsXML() {
- return OperationsContent.XML.bodyFor(databindProvider.currentContext().modelContext());
+ return OperationsContent.XML.bodyFor(
+ server.bindRequestRoot(databindProvider.currentContext()).inference());
}
/**
@Path("/operations/{identifier:.+}")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
public String getOperationXML(@PathParam("identifier") final String identifier) {
- return OperationsContent.XML.bodyFor(ParserIdentifier.toInstanceIdentifier(identifier,
- databindProvider.currentContext().modelContext(), mountPointService).inference());
+ return OperationsContent.XML.bodyFor(
+ server.bindRequestPath(databindProvider.currentContext(), identifier).inference());
}
}
import com.google.common.util.concurrent.MoreExecutors;
import java.util.List;
import java.util.Optional;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.SettableRestconfFuture;
public final class MdsalRestconfStrategy extends RestconfStrategy {
private final DOMDataBroker dataBroker;
- public MdsalRestconfStrategy(final EffectiveModelContext modelContext, final DOMDataBroker dataBroker) {
- super(modelContext);
+ public MdsalRestconfStrategy(final EffectiveModelContext modelContext, final DOMDataBroker dataBroker,
+ final @Nullable DOMRpcService rpcService) {
+ super(modelContext, rpcService);
this.dataBroker = requireNonNull(dataBroker);
}
import com.google.common.util.concurrent.SettableFuture;
import java.util.List;
import java.util.Optional;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.common.api.ReadFailedException;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
import org.opendaylight.restconf.common.errors.SettableRestconfFuture;
import org.opendaylight.yangtools.yang.common.Empty;
private final NetconfDataTreeService netconfService;
public NetconfRestconfStrategy(final EffectiveModelContext modelContext,
- final NetconfDataTreeService netconfService) {
- super(modelContext);
+ final NetconfDataTreeService netconfService, final @Nullable DOMRpcService rpcService) {
+ super(modelContext, rpcService);
this.netconfService = requireNonNull(netconfService);
}
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
import org.opendaylight.restconf.api.query.ContentParam;
private static final Logger LOG = LoggerFactory.getLogger(RestconfStrategy.class);
private final @NonNull EffectiveModelContext modelContext;
+ private final @Nullable DOMRpcService rpcService;
- RestconfStrategy(final EffectiveModelContext modelContext) {
+ RestconfStrategy(final EffectiveModelContext modelContext, final @Nullable DOMRpcService rpcService) {
this.modelContext = requireNonNull(modelContext);
+ this.rpcService = rpcService;
}
/**
*/
public static @Nullable RestconfStrategy forMountPoint(final EffectiveModelContext modelContext,
final DOMMountPoint mountPoint) {
+ final var rpcService = mountPoint.getService(DOMRpcService.class).orElse(null);
+
final var netconfService = mountPoint.getService(NetconfDataTreeService.class);
if (netconfService.isPresent()) {
- return new NetconfRestconfStrategy(modelContext, netconfService.orElseThrow());
+ return new NetconfRestconfStrategy(modelContext, netconfService.orElseThrow(), rpcService);
}
final var dataBroker = mountPoint.getService(DOMDataBroker.class);
if (dataBroker.isPresent()) {
- return new MdsalRestconfStrategy(modelContext, dataBroker.orElseThrow());
+ return new MdsalRestconfStrategy(modelContext, dataBroker.orElseThrow(), rpcService);
}
return null;
}
configMap.entrySet().stream().filter(x -> stateMap.containsKey(x.getKey())).forEach(
y -> builder.addChild((T) prepareData(y.getValue(), stateMap.get(y.getKey()))));
}
+
+ public @NonNull RestconfFuture<Optional<ContainerNode>> invokeRpc(final QName type, final ContainerNode input) {
+ final var ret = new SettableRestconfFuture<Optional<ContainerNode>>();
+
+ final var local = rpcService;
+ if (local != null) {
+ Futures.addCallback(local.invokeRpc(requireNonNull(type), requireNonNull(input)),
+ new FutureCallback<DOMRpcResult>() {
+ @Override
+ public void onSuccess(final DOMRpcResult response) {
+ final var errors = response.errors();
+ if (errors.isEmpty()) {
+ ret.set(Optional.ofNullable(response.value()));
+ } else {
+ LOG.debug("RPC invocation reported {}", response.errors());
+ ret.setFailure(new RestconfDocumentedException("RPC implementation reported errors", null,
+ response.errors()));
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable cause) {
+ LOG.debug("RPC invocation failed, cause");
+ if (cause instanceof RestconfDocumentedException ex) {
+ ret.setFailure(ex);
+ } else {
+ // TODO: YangNetconfErrorAware if we ever get into a broader invocation scope
+ ret.setFailure(new RestconfDocumentedException(cause,
+ new RestconfError(ErrorType.RPC, ErrorTag.OPERATION_FAILED, cause.getMessage())));
+ }
+ }
+ }, MoreExecutors.directExecutor());
+ } else {
+ LOG.debug("RPC invocation is not available");
+ ret.setFailure(new RestconfDocumentedException("RPC invocation is not available",
+ ErrorType.PROTOCOL, ErrorTag.OPERATION_NOT_SUPPORTED));
+ }
+ return ret;
+ }
}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
-import java.util.List;
import java.util.function.Function;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
-import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.nb.rfc8040.streams.listeners.ListenersBroker;
import org.opendaylight.yangtools.yang.common.ErrorTag;
@Test
public void createStreamTest() {
- final DOMRpcResult result = CreateStreamUtil.createDataChangeNotifiStream(listenersBroker,
- prepareDomPayload("create-data-change-event-subscription", RpcDefinition::getInput, "toaster", "path"),
- SCHEMA_CTX);
- assertEquals(List.of(), result.errors());
assertEquals(prepareDomPayload("create-data-change-event-subscription",
RpcDefinition::getOutput,
"data-change-event-subscription/toaster:toaster/datastore=CONFIGURATION/scope=BASE", "stream-name"),
- result.value());
+ CreateStreamUtil.createDataChangeNotifiStream(listenersBroker,
+ prepareDomPayload("create-data-change-event-subscription", RpcDefinition::getInput, "toaster", "path"),
+ SCHEMA_CTX));
}
@Test
--- /dev/null
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.restconf.nb.rfc8040.rests.services.impl;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.doReturn;
+
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMMountPoint;
+import org.opendaylight.mdsal.dom.api.DOMMountPointService;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
+
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
+public class MdsalRestconfServerTest extends AbstractJukeboxTest {
+ @Mock
+ private DOMMountPointService mountPointService;
+ @Mock
+ private DOMMountPoint mountPoint;
+ @Mock
+ private DOMDataBroker dataBroker;
+ @Mock
+ private NetconfDataTreeService netconfService;
+ @Mock
+ private DOMRpcService rpcService;
+
+ private MdsalRestconfServer server;
+
+ @Before
+ public void before() {
+ server = new MdsalRestconfServer(dataBroker, rpcService, mountPointService);
+ doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
+ }
+
+ @Test
+ public void testGetRestconfStrategyLocal() {
+ assertInstanceOf(MdsalRestconfStrategy.class, server.getRestconfStrategy(JUKEBOX_SCHEMA, null));
+ }
+
+ @Test
+ public void testGetRestconfStrategyMountDataBroker() {
+ doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
+ doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
+ assertInstanceOf(MdsalRestconfStrategy.class, server.getRestconfStrategy(JUKEBOX_SCHEMA, mountPoint));
+ }
+
+ @Test
+ public void testGetRestconfStrategyMountNetconfService() {
+ doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
+ assertInstanceOf(NetconfRestconfStrategy.class, server.getRestconfStrategy(JUKEBOX_SCHEMA, mountPoint));
+ }
+
+ @Test
+ public void testGetRestconfStrategyMountNone() {
+ doReturn(JUKEBOX_IID).when(mountPoint).getIdentifier();
+ doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
+ doReturn(Optional.empty()).when(mountPoint).getService(DOMDataBroker.class);
+ final var ex = assertThrows(RestconfDocumentedException.class,
+ () -> server.getRestconfStrategy(JUKEBOX_SCHEMA, mountPoint));
+ final var errors = ex.getErrors();
+ assertEquals(1, errors.size());
+ final var error = errors.get(0);
+ assertEquals(ErrorType.APPLICATION, error.getErrorType());
+ assertEquals(ErrorTag.OPERATION_FAILED, error.getErrorTag());
+ assertEquals("Could not find a supported access interface in mount point "
+ + "/(http://example.com/ns/example-jukebox?revision=2015-04-04)jukebox", error.getErrorMessage());
+ // FIXME: should be JUKEBOX_IID
+ assertNull(error.getErrorPath());
+ }
+}
import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
import org.opendaylight.restconf.nb.rfc8040.AbstractInstanceIdentifierTest;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
@Mock
private DOMActionService actionService;
@Mock
+ private DOMRpcService rpcService;
+ @Mock
private DOMMountPointService mountPointService;
@Mock
private RestconfStreamsSubscriptionService restconfStreamSubService;
Builders.containerBuilder().withNodeIdentifier(NodeIdentifier.create(OUTPUT_QNAME)).build())))
.when(actionService).invokeAction(eq(Absolute.of(CONT_QNAME, CONT1_QNAME, RESET_QNAME)), any(), any());
- final var dataService = new RestconfDataServiceImpl(
- () -> DatabindContext.ofModel(IID_SCHEMA), dataBroker, mountPointService, restconfStreamSubService,
+ final var dataService = new RestconfDataServiceImpl(() -> DatabindContext.ofModel(IID_SCHEMA),
+ new MdsalRestconfServer(dataBroker, rpcService, mountPointService), dataBroker, restconfStreamSubService,
actionService, new StreamsConfiguration(0, 1, 0, false));
final var response = dataService.postDataJSON("instance-identifier-module:cont/cont1/reset",
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
public class Netconf822Test {
- private static Inference INFERENCE;
+ private static final Absolute NEW1 = Absolute.of(QName.create("foo", "2021-09-30", "new1"));
+
+ private static EffectiveModelContext SCHEMA;
@BeforeClass
public static void beforeClass() {
- final var context = YangParserTestUtils.parseYangResourceDirectory("/nc822");
- INFERENCE = SchemaInferenceStack.of(context,
- Absolute.of(QName.create("foo", "new1", Revision.of("2021-09-30")))).toInference();
+ SCHEMA = YangParserTestUtils.parseYangResourceDirectory("/nc822");
}
@Test
"foo:new": [null],
"foo:new1": [null]
}
- }""", OperationsContent.JSON.bodyFor(INFERENCE.getEffectiveModelContext()));
+ }""", OperationsContent.JSON.bodyFor(SchemaInferenceStack.of(SCHEMA).toInference()));
}
@Test
"ietf-restconf:operations" : {
"foo:new1": [null]
}
- }""", OperationsContent.JSON.bodyFor(INFERENCE));
+ }""", OperationsContent.JSON.bodyFor(SchemaInferenceStack.of(SCHEMA, NEW1).toInference()));
}
@Test
xmlns:ns0="foo" >
<ns0:new/>
<ns0:new1/>
- </operations>""", OperationsContent.XML.bodyFor(INFERENCE.getEffectiveModelContext()));
+ </operations>""", OperationsContent.XML.bodyFor(SchemaInferenceStack.of(SCHEMA).toInference()));
}
@Test
<operations xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf"
xmlns:ns0="foo" >
<ns0:new1/>
- </operations>""", OperationsContent.XML.bodyFor(INFERENCE));
+ </operations>""", OperationsContent.XML.bodyFor(SchemaInferenceStack.of(SCHEMA, NEW1).toInference()));
}
}
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.patch.rev170222.yang.patch.yang.patch.Edit.Operation;
import org.opendaylight.yangtools.yang.common.ErrorTag;
@Mock
private DOMActionService actionService;
@Mock
+ private DOMRpcService rpcService;
+ @Mock
private RestconfStreamsSubscriptionService delegRestconfSubscrService;
@Mock
private MultivaluedMap<String, String> queryParamenters;
doReturn(read).when(dataBroker).newReadOnlyTransaction();
doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
- dataService = new RestconfDataServiceImpl(() -> DatabindContext.ofModel(JUKEBOX_SCHEMA), dataBroker,
- mountPointService, delegRestconfSubscrService, actionService, new StreamsConfiguration(0, 1, 0, false));
+ dataService = new RestconfDataServiceImpl(() -> DatabindContext.ofModel(JUKEBOX_SCHEMA),
+ new MdsalRestconfServer(dataBroker, rpcService, mountPointService), dataBroker, delegRestconfSubscrService,
+ actionService, new StreamsConfiguration(0, 1, 0, false));
doReturn(Optional.of(mountPoint)).when(mountPointService)
.getMountPoint(any(YangInstanceIdentifier.class));
doReturn(Optional.of(FixedDOMSchemaService.of(JUKEBOX_SCHEMA))).when(mountPoint)
.getService(DOMSchemaService.class);
doReturn(Optional.of(mountDataBroker)).when(mountPoint).getService(DOMDataBroker.class);
+ doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
doReturn(read).when(mountDataBroker).newReadOnlyTransaction();
doReturn(readWrite).when(mountDataBroker).newReadWriteTransaction();
final String errorMessage = status.editCollection().get(2).getEditErrors().get(0).getErrorMessage();
assertEquals("Data does not exist", errorMessage);
}
-
- @Test
- public void testGetRestconfStrategy() {
- var restconfStrategy = dataService.getRestconfStrategy(JUKEBOX_SCHEMA, mountPoint);
- assertTrue(restconfStrategy instanceof MdsalRestconfStrategy);
-
- doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
- restconfStrategy = dataService.getRestconfStrategy(JUKEBOX_SCHEMA, mountPoint);
- assertTrue(restconfStrategy instanceof NetconfRestconfStrategy);
- }
}
*/
package org.opendaylight.restconf.nb.rfc8040.rests.services.impl;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
-import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
+import com.google.common.util.concurrent.Futures;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
-import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.mdsal.dom.api.DOMRpcException;
import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException;
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
private static DatabindContext CONTEXT;
+ @Mock
+ private DOMDataBroker dataBroker;
@Mock
private DOMRpcService rpcService;
@Mock
private DOMMountPoint mountPoint;
@Mock
private DOMMountPointService mountPointService;
+
private RestconfInvokeOperationsServiceImpl invokeOperationsService;
+ private MdsalRestconfServer server;
@BeforeClass
public static void beforeClass() {
@Before
public void setup() {
- invokeOperationsService = new RestconfInvokeOperationsServiceImpl(() -> CONTEXT, rpcService, mountPointService,
+ server = new MdsalRestconfServer(dataBroker, rpcService, mountPointService);
+ invokeOperationsService = new RestconfInvokeOperationsServiceImpl(() -> CONTEXT, server, mountPointService,
new StreamsConfiguration(0, 1, 0, false));
}
prepNNC(result);
final var ar = mock(AsyncResponse.class);
- final var captor = ArgumentCaptor.forClass(Response.class);
+ final var response = ArgumentCaptor.forClass(Response.class);
invokeOperationsService.invokeRpcJSON("invoke-rpc-module:rpc-test", new ByteArrayInputStream("""
{
"invoke-rpc-module:input" : {
}
}
""".getBytes(StandardCharsets.UTF_8)), mock(UriInfo.class), ar);
- verify(ar).resume(captor.capture());
+ verify(ar).resume(response.capture());
- final var response = captor.getValue();
- assertEquals(204, response.getStatus());
+ assertEquals(204, response.getValue().getStatus());
}
@Test
- public void invokeRpcTest() throws InterruptedException, ExecutionException {
- final DOMRpcResult mockResult = new DefaultDOMRpcResult(OUTPUT, List.of());
- doReturn(immediateFluentFuture(mockResult)).when(rpcService).invokeRpc(RPC, INPUT);
- final DOMRpcResult rpcResult = RestconfInvokeOperationsServiceImpl.invokeRpc(INPUT, RPC, rpcService).get();
- assertTrue(rpcResult.errors().isEmpty());
- assertEquals(OUTPUT, rpcResult.value());
+ public void invokeRpcTest() throws Exception {
+ doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of()))).when(rpcService)
+ .invokeRpc(RPC, INPUT);
+ assertEquals(Optional.of(OUTPUT), Futures.getDone(server.getRestconfStrategy(CONTEXT.modelContext(), null)
+ .invokeRpc(RPC, INPUT)));
}
@Test
- public void invokeRpcErrorsAndCheckTestTest() throws InterruptedException, ExecutionException {
- final QName errorRpc = QName.create(RPC, "error-rpc");
- final DOMRpcException exception = new DOMRpcImplementationNotAvailableException(
+ public void invokeRpcErrorsAndCheckTestTest() throws Exception {
+ final var errorRpc = QName.create(RPC, "error-rpc");
+ final var exception = new DOMRpcImplementationNotAvailableException(
"No implementation of RPC " + errorRpc + " available.");
- doReturn(immediateFailedFluentFuture(exception)).when(rpcService).invokeRpc(errorRpc, INPUT);
- final DOMRpcResult rpcResult = RestconfInvokeOperationsServiceImpl.invokeRpc(INPUT, errorRpc, rpcService).get();
- assertNull(rpcResult.value());
- final Collection<? extends RpcError> errorList = rpcResult.errors();
+ doReturn(Futures.immediateFailedFuture(exception)).when(rpcService).invokeRpc(errorRpc, INPUT);
+ final var ex = assertInstanceOf(RestconfDocumentedException.class,
+ assertThrows(ExecutionException.class, () -> Futures.getDone(
+ server.getRestconfStrategy(CONTEXT.modelContext(), null).invokeRpc(errorRpc, INPUT))).getCause());
+ final var errorList = ex.getErrors();
assertEquals(1, errorList.size());
- final RpcError actual = errorList.iterator().next();
- assertEquals("No implementation of RPC " + errorRpc + " available.", actual.getMessage());
- assertEquals(ErrorTag.OPERATION_FAILED, actual.getTag());
+ final var actual = errorList.iterator().next();
+ assertEquals("No implementation of RPC " + errorRpc + " available.", actual.getErrorMessage());
assertEquals(ErrorType.RPC, actual.getErrorType());
+ assertEquals(ErrorTag.OPERATION_FAILED, actual.getErrorTag());
}
@Test
- public void invokeRpcViaMountPointTest() throws InterruptedException, ExecutionException {
- doReturn(Optional.ofNullable(rpcService)).when(mountPoint).getService(DOMRpcService.class);
- final DOMRpcResult mockResult = new DefaultDOMRpcResult(OUTPUT, List.of());
- doReturn(immediateFluentFuture(mockResult)).when(rpcService).invokeRpc(RPC, INPUT);
- final DOMRpcResult rpcResult = RestconfInvokeOperationsServiceImpl.invokeRpc(INPUT, RPC, mountPoint).get();
- assertTrue(rpcResult.errors().isEmpty());
- assertEquals(OUTPUT, rpcResult.value());
+ public void invokeRpcViaMountPointTest() throws Exception {
+ doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
+ doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
+ doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
+ doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of()))).when(rpcService)
+ .invokeRpc(RPC, INPUT);
+ assertEquals(Optional.of(OUTPUT), Futures.getDone(
+ server.getRestconfStrategy(CONTEXT.modelContext(), mountPoint).invokeRpc(RPC, INPUT)));
}
@Test
public void invokeRpcMissingMountPointServiceTest() {
doReturn(Optional.empty()).when(mountPoint).getService(DOMRpcService.class);
- assertThrows(RestconfDocumentedException.class,
- () -> RestconfInvokeOperationsServiceImpl.invokeRpc(INPUT, RPC, mountPoint));
+ doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
+ doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
+ final var strategy = server.getRestconfStrategy(CONTEXT.modelContext(), mountPoint);
+ final var ex = assertInstanceOf(RestconfDocumentedException.class,
+ assertThrows(ExecutionException.class, () -> Futures.getDone(strategy.invokeRpc(RPC, INPUT))).getCause());
+ final var errors = ex.getErrors();
+ assertEquals(1, errors.size());
+ final var error = errors.get(0);
+ assertEquals(ErrorType.PROTOCOL, error.getErrorType());
+ assertEquals(ErrorTag.OPERATION_NOT_SUPPORTED, error.getErrorTag());
+ assertEquals("RPC invocation is not available", error.getErrorMessage());
}
@Test
- public void checkResponseTest() throws InterruptedException, ExecutionException {
- doReturn(immediateFluentFuture(new DefaultDOMRpcResult(OUTPUT, List.of())))
+ public void checkResponseTest() throws Exception {
+ doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of())))
.when(rpcService).invokeRpc(RPC, INPUT);
- final DOMRpcResult rpcResult = RestconfInvokeOperationsServiceImpl.invokeRpc(INPUT, RPC, rpcService).get();
- assertTrue(rpcResult.errors().isEmpty());
- assertEquals(OUTPUT, rpcResult.value());
+ assertEquals(Optional.of(OUTPUT), Futures.getDone(
+ server.getRestconfStrategy(CONTEXT.modelContext(), null).invokeRpc(RPC, INPUT)));
}
private void prepNNC(final ContainerNode result) {
- final QName qname = QName.create("invoke:rpc:module", "2013-12-03", "rpc-test");
- final DOMRpcResult domRpcResult = mock(DOMRpcResult.class);
- doReturn(immediateFluentFuture(domRpcResult)).when(rpcService).invokeRpc(eq(qname), any(ContainerNode.class));
+ final var qname = QName.create("invoke:rpc:module", "2013-12-03", "rpc-test");
+ final var domRpcResult = mock(DOMRpcResult.class);
+ doReturn(Futures.immediateFuture(domRpcResult)).when(rpcService).invokeRpc(eq(qname), any(ContainerNode.class));
doReturn(result).when(domRpcResult).value();
}
}
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
import org.opendaylight.yang.gen.v1.module._1.rev140101.Module1Data;
private DOMMountPoint mountPoint;
@Mock
private DOMSchemaService schemaService;
+ @Mock
+ private DOMDataBroker dataBroker;
+ @Mock
+ private DOMRpcService rpcService;
private RestconfOperationsServiceImpl opService;
doReturn(SCHEMA).when(schemaService).getGlobalContext();
doReturn(Optional.of(schemaService)).when(mountPoint).getService(DOMSchemaService.class);
doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(any());
- opService = new RestconfOperationsServiceImpl(() -> DatabindContext.ofModel(SCHEMA), mountPointService);
+
+ opService = new RestconfOperationsServiceImpl(() -> DatabindContext.ofModel(SCHEMA),
+ new MdsalRestconfServer(dataBroker, rpcService, mountPointService));
}
@Test
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.restconf.api.query.ContentParam;
import org.opendaylight.restconf.api.query.WithDefaultsParam;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
private DOMDataBroker mockDataBroker;
@Mock
private DOMDataTreeReadTransaction read;
+ @Mock
+ private DOMRpcService rpcService;
@BeforeClass
public static void setupModulesSchema() {
// assert that data to delete exists
when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
.thenReturn(immediateTrueFluentFuture());
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
// assert that data to delete does NOT exist
when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
.thenReturn(immediateFalseFluentFuture());
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, entryNode);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doReturn(immediateFailedFluentFuture(domException)).when(readWrite).commit();
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Test
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
+ new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
}
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker).putData(GAP_IID, GAP_LEAF, null);
+ new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null).putData(GAP_IID, GAP_LEAF, null);
verify(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
}
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
+ new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
}
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
RestconfStrategy testPatchContainerDataStrategy() {
doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
RestconfStrategy testPatchLeafDataStrategy() {
doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
RestconfStrategy testPatchListDataStrategy() {
doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy() {
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, PLAYER_IID);
doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
CREATE_AND_DELETE_TARGET);
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
RestconfStrategy testPatchMergePutContainerStrategy() {
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
RestconfStrategy deleteNonexistentDataTestStrategy() {
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
CREATE_AND_DELETE_TARGET);
- return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker, null);
}
@Override
doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.CONFIGURATION, PATH);
doReturn(immediateFluentFuture(Optional.empty())).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_2);
doReturn(immediateFluentFuture(Optional.empty())).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_2);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH_2);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.CONFIGURATION, PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.CONFIGURATION, PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_3);
doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_3);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_3);
doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_3);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_3);
doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_3);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Override
RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
doReturn(immediateFluentFuture(Optional.empty())).when(read).read(LogicalDatastoreType.CONFIGURATION, PATH_2);
- return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker, null);
}
@Test
doReturn(immediateFluentFuture(Optional.of(data))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, path);
- assertEquals(data, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker).readData(ContentParam.ALL, path,
- WithDefaultsParam.TRIM));
+ assertEquals(data, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker, null)
+ .readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
}
@Test
doReturn(immediateFluentFuture(Optional.of(data))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, path);
- assertEquals(data, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker).readData(ContentParam.ALL, path,
- WithDefaultsParam.TRIM));
+ assertEquals(data, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker, null)
+ .readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
}
@Test
doReturn(immediateFluentFuture(Optional.of(content))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, path);
- assertEquals(content, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker).readData(ContentParam.ALL, path,
- WithDefaultsParam.TRIM));
+ assertEquals(content, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker, null)
+ .readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
}
}
@Override
RestconfStrategy testDeleteDataStrategy() {
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
doReturn(Futures.immediateFailedFuture(new TransactionCommitFailedException(
"Commit of transaction " + this + " failed", new NetconfDocumentedException("id",
ErrorType.RPC, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR)))).when(netconfService).commit();
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.create(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).create(
LogicalDatastoreType.CONFIGURATION, node, entryNode, Optional.empty());
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
.create(any(), any(), any(), any());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).discardChanges();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
RestconfStrategy testPatchContainerDataStrategy() {
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).merge(any(), any(),any(),
any());
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.merge(any(), any(), any(), any());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.merge(any(), any(),any(),any());
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Test
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
- new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
verify(netconfService).lock();
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
- new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
- new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(GAP_IID, GAP_LEAF, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(GAP_IID, GAP_LEAF, null);
verify(netconfService).getConfig(GAP_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
}
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
- new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(GAP_IID, GAP_LEAF, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(GAP_IID, GAP_LEAF, null);
verify(netconfService).getConfig(GAP_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
}
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
- new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null)
+ .putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
- new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null)
+ .putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
// FIXME: exact match
.replace(any(), any(), any(), any());
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
.create(LogicalDatastoreType.CONFIGURATION, PLAYER_IID, EMPTY_JUKEBOX, Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
RestconfStrategy testPatchMergePutContainerStrategy() {
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
.when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
- return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
}
@Override
@Override
RestconfStrategy readDataConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readAllHavingOnlyConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).get(PATH);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readAllHavingOnlyNonConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readDataNonConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readContainerDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readListDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(LIST_DATA))).when(netconfService).get(PATH_3);
doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(netconfService).getConfig(PATH_3);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readOrderedListDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_1))).when(netconfService).get(PATH_3);
doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(netconfService).getConfig(PATH_3);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readUnkeyedListDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_1))).when(netconfService).get(PATH_3);
doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(netconfService).getConfig(PATH_3);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
.get(LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(netconfService)
.getConfig(LEAF_SET_NODE_PATH);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
.get(LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(netconfService)
.getConfig(LEAF_SET_NODE_PATH);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
@Override
RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
- return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
}
}