*/
package org.opendaylight.controller.sal.rest.api;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+ @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+ Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+ @POST
+ @Path("/operations/{identifier}")
+ @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+ Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+ public StructuredData invokeRpc(@PathParam("identifier") String identifier);
+
@GET
@Path("/config/{identifier:.+}")
@Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
@PUT
@Path("/config/{identifier:.+}")
- @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
@POST
@Path("/config/{identifier:.+}")
- @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
@POST
@Path("/config")
- @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
+ @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response createConfigurationData(CompositeNode payload);
+ @DELETE
+ @Path("/config/{identifier:.+}")
+ public Response deleteConfigurationData(@PathParam("identifier") String identifier);
+
}
package org.opendaylight.controller.sal.rest.api;
+import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@Deprecated
@POST
@Path("/datastore/{identifier:.+}")
- @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+ @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
@Deprecated
@PUT
@Path("/datastore/{identifier:.+}")
- @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+ @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
val transaction = dataService.beginTransaction;
LOG.info("Put Configuration via Restconf: {}", path)
transaction.putConfigurationData(path, payload);
- return transaction.commit()
+ return transaction.commit
}
def commitConfigurationDataPost(InstanceIdentifier path, CompositeNode payload) {
transaction.putConfigurationData(path, payload);
if (payload == transaction.createdConfigurationData.get(path)) {
LOG.info("Post Configuration via Restconf: {}", path)
- return transaction.commit()
+ return transaction.commit
}
LOG.info("Post Configuration via Restconf was not executed because data already exists: {}", path)
return null;
}
+ def commitConfigurationDataDelete(InstanceIdentifier path) {
+ checkPreconditions
+ val transaction = dataService.beginTransaction;
+ transaction.removeConfigurationData(path)
+ return transaction.commit
+ }
+
}
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
import static javax.ws.rs.core.Response.Status.*
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
class RestconfImpl implements RestconfService {
}
override invokeRpc(String identifier, CompositeNode payload) {
- val rpc = identifier.rpcDefinition
+ return callRpc(identifier.rpcDefinition, payload)
+ }
+
+ override invokeRpc(String identifier) {
+ return callRpc(identifier.rpcDefinition, null)
+ }
+
+ private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) {
if (rpc === null) {
throw new ResponseException(NOT_FOUND, "RPC does not exist.");
}
- val value = normalizeNode(payload, rpc.input, null)
- val List<Node<?>> input = new ArrayList
- input.add(value)
- val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
+ var CompositeNode rpcRequest;
+ if (payload === null) {
+ rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, null, null, null)
+ } else {
+ val value = normalizeNode(payload, rpc.input, null)
+ val List<Node<?>> input = new ArrayList
+ input.add(value)
+ rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
+ }
val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest);
if (!rpcResult.successful) {
throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed")
default: Response.status(INTERNAL_SERVER_ERROR).build
}
}
+
+ override deleteConfigurationData(String identifier) {
+ val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
+ val status = broker.commitConfigurationDataDelete(instanceIdentifierWithSchemaNode.getInstanceIdentifier).get;
+ switch status.result {
+ case TransactionStatus.COMMITED: Response.status(OK).build
+ default: Response.status(INTERNAL_SERVER_ERROR).build
+ }
+ }
private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
val identifierWithSchemaNode = identifier.toInstanceIdentifier
for (key : listNode.keyDefinition) {
val dataNodeKeyValueObject = dataNode.getSimpleNodesByName(key.localName)?.head?.value
if (dataNodeKeyValueObject === null) {
- throw new ResponseException(BAD_REQUEST, "List " + dataNode.nodeType.localName + " does not contain key: " + key.localName)
+ throw new ResponseException(BAD_REQUEST, "Data contains list \"" + dataNode.nodeType.localName + "\" which does not contain key: \"" + key.localName + "\"")
}
keyValues.put(key, dataNodeKeyValueObject);
}
InstanceIdentifier mountPoint) {
if (schema === null) {
throw new ResponseException(BAD_REQUEST,
- "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
+ "Data has bad format.\n\"" + nodeBuilder.localName + "\" does not exist in yang schema.");
}
var validQName = schema.QName
var currentAugment = previousAugment;
nodeBuilder.qname = validQName
} else {
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 + ".\nIf data is in Json format then module name for " +
- nodeBuilder.localName + " should be " + moduleName + ".");
+ "Data has bad format.\nIf data is in XML format then namespace for \"" + nodeBuilder.localName +
+ "\" should be \"" + schema.QName.namespace + "\".\nIf data is in Json format then module name for \"" +
+ nodeBuilder.localName + "\" should be \"" + moduleName + "\".");
}
if (nodeBuilder instanceof CompositeNodeWrapper) {
}
if (!foundKey) {
throw new ResponseException(BAD_REQUEST,
- "Missing key \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"")
+ "Missing key in URI \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"")
}
}
}
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static org.junit.Assert.*;
import java.net.URI;
import java.net.URISyntaxException;
@Test
public void namespaceNotNullAndInvalidNamespaceAndNoModuleNameTest() {
- String exceptionMessage = null;
+ boolean exceptionReised = false;
try {
TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath);
} catch (ResponseException e) {
- exceptionMessage = String.valueOf(e.getResponse().getEntity());
+ exceptionReised = true;
}
- assertEquals(
- exceptionMessage,
- "Data has bad format.\nIf data is in XML format then namespace for cont should be normalize:node:module.\nIf data is in Json format then module name for cont should be normalize-node-module.");
+ assertTrue(exceptionReised);
}
@Test
assertEquals(204, response.getStatus());
uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
+ entity = Entity.entity(xml, MEDIA_TYPE);
response = target(uri).request(MEDIA_TYPE).put(entity);
assertEquals(200, response.getStatus());
uri = createUri("/datastore/", "ietf-interfaces:interfaces");
+ entity = Entity.entity(xml, MEDIA_TYPE);
response = target(uri).request(MEDIA_TYPE).post(entity);
assertEquals(204, response.getStatus());
}
assertEquals(500, response.getStatus());
uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
- response = target(uri).request(MEDIA_TYPE).put(entity);
+ entity = Entity.entity(xml, MEDIA_TYPE);
+ response = target(uri).request().put(entity);
assertEquals(500, response.getStatus());
- response = target(uri).request(MEDIA_TYPE).post(entity);
+ response = target(uri).request().accept(MEDIA_TYPE).post(entity);
assertEquals(500, response.getStatus());
}