From 32a108962f202a1e44fce818037301dfdb6f7566 Mon Sep 17 00:00:00 2001 From: msunal Date: Thu, 5 Dec 2013 11:35:43 +0100 Subject: [PATCH] Corrected response status codes from restconf - POST /restconf/config/* - 204 no msg body - POST /restconf/operations/* - 200 msg body or 204 no msg body or 500 operation failed - PUT /restconf/config/* - 200 no msg body Change-Id: Ida5759499f876c5fce8280510ffe4093ee1c03c3 Signed-off-by: Martin Sunal --- .../impl/StructuredDataToJsonProvider.java | 3 +- .../sal/restconf/impl/RestconfImpl.xtend | 86 ++++++++++--------- .../impl/test/InvokeRpcMethodTest.java | 2 +- .../restconf/impl/test/XmlProvidersTest.java | 12 +-- 4 files changed, 56 insertions(+), 47 deletions(-) diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java index 7022db2bc9..04114fa0ed 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java @@ -17,6 +17,7 @@ import javax.ws.rs.ext.Provider; import org.opendaylight.controller.sal.rest.api.Draft01; import org.opendaylight.controller.sal.rest.api.Draft02; import org.opendaylight.controller.sal.rest.api.RestconfService; +import org.opendaylight.controller.sal.restconf.impl.ResponseException; import org.opendaylight.controller.sal.restconf.impl.StructuredData; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; @@ -45,7 +46,7 @@ public enum StructuredDataToJsonProvider implements MessageBodyWriter> input = new ArrayList input.add(value) val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null) val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest); - return new StructuredData(rpcResult.result, rpc.output); + if (!rpcResult.successful) { + throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed") + } + if (rpcResult.result === null) { + return null + } + return new StructuredData(rpcResult.result, rpc.output) } - + override readConfigurationData(String identifier) { val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier); return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode) } - + override readOperationalData(String identifier) { val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier); return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode) } - + override updateConfigurationDataLegacy(String identifier, CompositeNode payload) { - updateConfigurationData(identifier,payload); + updateConfigurationData(identifier, payload); } - + override createConfigurationDataLegacy(String identifier, CompositeNode payload) { - createConfigurationData(identifier,payload); + createConfigurationData(identifier, payload); } - + private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) { val identifierWithSchemaNode = identifier.toInstanceIdentifier if (identifierWithSchemaNode === null) { - throw new ResponseException(Response.Status.BAD_REQUEST, "URI has bad format"); + throw new ResponseException(BAD_REQUEST, "URI has bad format"); } return identifierWithSchemaNode } - + private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) { if (node instanceof CompositeNodeWrapper) { - normalizeNode(node as CompositeNodeWrapper, schema,null) + normalizeNode(node as CompositeNodeWrapper, schema, null) return (node as CompositeNodeWrapper).unwrap() } return node } - private def void normalizeNode(NodeWrapper nodeBuilder, DataSchemaNode schema,QName previousAugment) { + private def void normalizeNode(NodeWrapper nodeBuilder, DataSchemaNode schema, QName previousAugment) { if (schema === null) { - throw new ResponseException(Response.Status.BAD_REQUEST, + throw new ResponseException(BAD_REQUEST, "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema."); } var validQName = schema.QName var currentAugment = previousAugment; - if(schema.augmenting) { + if (schema.augmenting) { currentAugment = schema.QName - } else if(previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) { - validQName = QName.create(currentAugment,schema.QName.localName); + } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) { + validQName = QName.create(currentAugment, schema.QName.localName); } val moduleName = controllerContext.findModuleByNamespace(validQName.namespace); if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace || nodeBuilder.namespace.path == moduleName) { nodeBuilder.qname = validQName } else { - throw new ResponseException(Response.Status.BAD_REQUEST, + throw new ResponseException(BAD_REQUEST, "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName + " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " + nodeBuilder.localName + " should be " + moduleName + "."); } - + if (nodeBuilder instanceof CompositeNodeWrapper) { val List> children = (nodeBuilder as CompositeNodeWrapper).getValues for (child : children) { normalizeNode(child, - findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),currentAugment) + findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes), + currentAugment) } } else if (nodeBuilder instanceof SimpleNodeWrapper) { val simpleNode = (nodeBuilder as SimpleNodeWrapper) val stringValue = simpleNode.value as String; - + val objectValue = TypeDefinitionAwareCodec.from(schema.typeDefinition)?.deserialize(stringValue); simpleNode.setValue(objectValue) } else if (nodeBuilder instanceof EmptyNodeWrapper) { val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper - if(schema instanceof LeafSchemaNode) { + if (schema instanceof LeafSchemaNode) { emptyNodeBuilder.setComposite(false); - } else if(schema instanceof ContainerSchemaNode) { + } else if (schema instanceof ContainerSchemaNode) { + // FIXME: Add presence check emptyNodeBuilder.setComposite(true); } } } - + private def dispatch TypeDefinition typeDefinition(LeafSchemaNode node) { node.type } - + private def dispatch TypeDefinition typeDefinition(LeafListSchemaNode node) { node.type } - - + private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set schemas) { for (schema : schemas) { if (schema instanceof ChoiceNode) { for (caze : (schema as ChoiceNode).cases) { - val result = findFirstSchemaByLocalName(localName, caze.childNodes) + val result = findFirstSchemaByLocalName(localName, caze.childNodes) if (result !== null) { return result } } } else { val result = schemas.findFirst[n|n.QName.localName.equals(localName)] - if(result !== null) { + if (result !== null) { return result; - + } } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java index 103c9ed3cd..d58b7e9dab 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java @@ -27,7 +27,7 @@ public class InvokeRpcMethodTest { @Override public RpcResult answer(InvocationOnMock invocation) throws Throwable { CompositeNode compNode = (CompositeNode) invocation.getArguments()[1]; - return new DummyRpcResult.Builder().result(compNode).build(); + return new DummyRpcResult.Builder().result(compNode).isSuccessful(true).build(); } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java index 5b0eea3212..ec7dba67b9 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java @@ -133,21 +133,21 @@ public class XmlProvidersTest extends JerseyTest { String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0"); Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity); - assertEquals(204, response.getStatus()); - response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity); assertEquals(200, response.getStatus()); + response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity); + assertEquals(204, response.getStatus()); uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0"); response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity); - assertEquals(204, response.getStatus()); - response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity); assertEquals(200, response.getStatus()); + response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity); + assertEquals(204, response.getStatus()); uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0"); response = target(uri).request(MEDIA_TYPE).put(entity); - assertEquals(204, response.getStatus()); - response = target(uri).request(MEDIA_TYPE).post(entity); assertEquals(200, response.getStatus()); + response = target(uri).request(MEDIA_TYPE).post(entity); + assertEquals(204, response.getStatus()); } @Test -- 2.36.6