use of org.opendaylight.restconf.common.errors.RestconfDocumentedException in project netconf by opendaylight.
the class RestconfImpl method subscribeToStream.
/**
* Subscribes to some path in schema context (stream) to listen on changes
* on this stream.
*
* <p>
* Additional parameters for subscribing to stream are loaded via rpc input
* parameters:
* <ul>
* <li>datastore - default CONFIGURATION (other values of
* {@link LogicalDatastoreType} enum type)</li>
* <li>scope - default BASE (other values of {@link Scope})</li>
* </ul>
*/
@Override
public NormalizedNodeContext subscribeToStream(final String identifier, final UriInfo uriInfo) {
boolean startTimeUsed = false;
boolean stopTimeUsed = false;
Instant start = Instant.now();
Instant stop = null;
boolean filterUsed = false;
String filter = null;
boolean leafNodesOnlyUsed = false;
boolean leafNodesOnly = false;
boolean skipNotificationDataUsed = false;
boolean skipNotificationData = false;
for (final Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
switch(entry.getKey()) {
case "start-time":
if (!startTimeUsed) {
startTimeUsed = true;
start = parseDateFromQueryParam(entry);
} else {
throw new RestconfDocumentedException("Start-time parameter can be used only once.");
}
break;
case "stop-time":
if (!stopTimeUsed) {
stopTimeUsed = true;
stop = parseDateFromQueryParam(entry);
} else {
throw new RestconfDocumentedException("Stop-time parameter can be used only once.");
}
break;
case "filter":
if (!filterUsed) {
filterUsed = true;
filter = entry.getValue().iterator().next();
} else {
throw new RestconfDocumentedException("Filter parameter can be used only once.");
}
break;
case "odl-leaf-nodes-only":
if (!leafNodesOnlyUsed) {
leafNodesOnlyUsed = true;
leafNodesOnly = Boolean.parseBoolean(entry.getValue().iterator().next());
} else {
throw new RestconfDocumentedException("Odl-leaf-nodes-only parameter can be used only once.");
}
break;
case "odl-skip-notification-data":
if (!skipNotificationDataUsed) {
skipNotificationDataUsed = true;
skipNotificationData = Boolean.parseBoolean(entry.getValue().iterator().next());
} else {
throw new RestconfDocumentedException("Odl-skip-notification-data parameter can be used only once.");
}
break;
default:
throw new RestconfDocumentedException("Bad parameter used with notifications: " + entry.getKey());
}
}
if (!startTimeUsed && stopTimeUsed) {
throw new RestconfDocumentedException("Stop-time parameter has to be used with start-time parameter.");
}
URI response = null;
if (identifier.contains(DATA_SUBSCR)) {
response = dataSubs(identifier, uriInfo, start, stop, filter, leafNodesOnly, skipNotificationData);
} else if (identifier.contains(NOTIFICATION_STREAM)) {
response = notifStream(identifier, uriInfo, start, stop, filter);
}
if (response != null) {
// prepare node with value of location
final InstanceIdentifierContext<?> iid = prepareIIDSubsStreamOutput();
final NormalizedNodeBuilder<NodeIdentifier, Object, LeafNode<Object>> builder = ImmutableLeafNodeBuilder.create().withValue(response.toString());
builder.withNodeIdentifier(NodeIdentifier.create(QName.create("subscribe:to:notification", "2016-10-28", "location")));
// prepare new header with location
return new NormalizedNodeContext(iid, builder.build(), ImmutableMap.of("Location", response));
}
final String msg = "Bad type of notification of sal-remote";
LOG.warn(msg);
throw new RestconfDocumentedException(msg);
}
use of org.opendaylight.restconf.common.errors.RestconfDocumentedException in project netconf by opendaylight.
the class RestconfImpl method checkRpcResponse.
@SuppressWarnings("checkstyle:avoidHidingCauseException")
private static DOMRpcResult checkRpcResponse(final ListenableFuture<? extends DOMRpcResult> response) {
if (response == null) {
return null;
}
try {
final DOMRpcResult retValue = response.get();
if (retValue.getErrors().isEmpty()) {
return retValue;
}
LOG.debug("RpcError message {}", retValue.getErrors());
throw new RestconfDocumentedException("RpcError message", null, retValue.getErrors());
} catch (final InterruptedException e) {
final String errMsg = "The operation was interrupted while executing and did not complete.";
LOG.debug("Rpc Interrupt - {}", errMsg, e);
throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION, e);
} catch (final ExecutionException e) {
LOG.debug("Execution RpcError: ", e);
Throwable cause = e.getCause();
if (cause == null) {
throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.", e);
}
while (cause.getCause() != null) {
cause = cause.getCause();
}
if (cause instanceof IllegalArgumentException) {
throw new RestconfDocumentedException(cause.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
} else if (cause instanceof DOMRpcImplementationNotAvailableException) {
throw new RestconfDocumentedException(cause.getMessage(), ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED);
}
throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.", cause);
} catch (final CancellationException e) {
final String errMsg = "The operation was cancelled while executing.";
LOG.debug("Cancel RpcExecution: {}", errMsg, e);
throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION);
}
}
use of org.opendaylight.restconf.common.errors.RestconfDocumentedException in project netconf by opendaylight.
the class BrokerFacade method patchConfigurationDataWithinTransaction.
public PatchStatusContext patchConfigurationDataWithinTransaction(final PatchContext patchContext) throws Exception {
final DOMMountPoint mountPoint = patchContext.getInstanceIdentifierContext().getMountPoint();
// get new transaction and schema context on server or on mounted device
final EffectiveModelContext schemaContext;
final DOMDataTreeReadWriteTransaction patchTransaction;
if (mountPoint == null) {
schemaContext = patchContext.getInstanceIdentifierContext().getSchemaContext();
patchTransaction = this.domDataBroker.newReadWriteTransaction();
} else {
schemaContext = modelContext(mountPoint);
final Optional<DOMDataBroker> optional = mountPoint.getService(DOMDataBroker.class);
if (optional.isPresent()) {
patchTransaction = optional.get().newReadWriteTransaction();
} else {
// if mount point does not have broker it is not possible to continue and global error is reported
LOG.error("Http Patch {} has failed - device {} does not support broker service", patchContext.getPatchId(), mountPoint.getIdentifier());
return new PatchStatusContext(patchContext.getPatchId(), null, false, ImmutableList.of(new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "DOM data broker service isn't available for mount point " + mountPoint.getIdentifier())));
}
}
final List<PatchStatusEntity> editCollection = new ArrayList<>();
List<RestconfError> editErrors;
boolean withoutError = true;
for (final PatchEntity patchEntity : patchContext.getData()) {
final PatchEditOperation operation = patchEntity.getOperation();
switch(operation) {
case CREATE:
if (withoutError) {
try {
postDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(), patchEntity.getNode(), schemaContext);
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null));
} catch (final RestconfDocumentedException e) {
LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString());
editErrors = new ArrayList<>();
editErrors.addAll(e.getErrors());
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors));
withoutError = false;
}
}
break;
case REPLACE:
if (withoutError) {
try {
putDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(), patchEntity.getNode(), schemaContext);
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null));
} catch (final RestconfDocumentedException e) {
LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString());
editErrors = new ArrayList<>();
editErrors.addAll(e.getErrors());
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors));
withoutError = false;
}
}
break;
case DELETE:
case REMOVE:
if (withoutError) {
try {
deleteDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode());
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null));
} catch (final RestconfDocumentedException e) {
LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString());
editErrors = new ArrayList<>();
editErrors.addAll(e.getErrors());
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors));
withoutError = false;
}
}
break;
case MERGE:
if (withoutError) {
try {
mergeDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(), patchEntity.getNode(), schemaContext);
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null));
} catch (final RestconfDocumentedException e) {
LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString());
editErrors = new ArrayList<>();
editErrors.addAll(e.getErrors());
editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors));
withoutError = false;
}
}
break;
default:
LOG.error("Unsupported http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString());
break;
}
}
// if errors then cancel transaction and return error status
if (!withoutError) {
patchTransaction.cancel();
return new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), false, null);
}
// if no errors commit transaction
final CountDownLatch waiter = new CountDownLatch(1);
final FluentFuture<? extends CommitInfo> future = patchTransaction.commit();
final PatchStatusContextHelper status = new PatchStatusContextHelper();
future.addCallback(new FutureCallback<CommitInfo>() {
@Override
public void onSuccess(final CommitInfo result) {
status.setStatus(new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), true, null));
waiter.countDown();
}
@Override
public void onFailure(final Throwable throwable) {
// if commit failed it is global error
LOG.error("Http Patch {} transaction commit has failed", patchContext.getPatchId());
status.setStatus(new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), false, ImmutableList.of(new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, throwable.getMessage()))));
waiter.countDown();
}
}, MoreExecutors.directExecutor());
waiter.await();
return status.getStatus();
}
use of org.opendaylight.restconf.common.errors.RestconfDocumentedException in project netconf by opendaylight.
the class NotificationListenerAdapter method writeBodyToString.
private static String writeBodyToString(final EffectiveModelContext schemaContext, final DOMNotification notification) {
final Writer writer = new StringWriter();
final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter.createExclusiveWriter(JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(schemaContext), notification.getType().asSchemaPath(), null, JsonWriterFactory.createJsonWriter(writer));
final NormalizedNodeWriter nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream);
try {
nodeWriter.write(notification.getBody());
nodeWriter.close();
} catch (final IOException e) {
throw new RestconfDocumentedException("Problem while writing body of notification to JSON. ", e);
}
return writer.toString();
}
use of org.opendaylight.restconf.common.errors.RestconfDocumentedException in project netconf by opendaylight.
the class JsonToNnTest method emptyDataReadTest.
@Test
public void emptyDataReadTest() throws Exception {
final NormalizedNodeContext normalizedNodeContext = prepareNNC("/json-to-nn/empty-data.json", "array-with-null-yang:cont");
assertNotNull(normalizedNodeContext);
assertEquals("cont", normalizedNodeContext.getData().getIdentifier().getNodeType().getLocalName());
final String dataTree = NormalizedNodes.toStringTree(normalizedNodeContext.getData());
assertTrue(dataTree.contains("lflst1"));
assertTrue(dataTree.contains("lflst2 45"));
RestconfDocumentedException exception = null;
mockBodyReader("array-with-null-yang:cont", this.jsonBodyReader, false);
final InputStream inputStream = this.getClass().getResourceAsStream("/json-to-nn/empty-data.json1");
try {
this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, inputStream);
} catch (final RestconfDocumentedException e) {
exception = e;
}
assertNotNull(exception);
assertEquals("Error parsing input: null", exception.getErrors().get(0).getErrorMessage());
}
Aggregations