Support REST optical intent creation
Change-Id: I3b040ad7a337cb1b145bcbd3d0e5fdb5406334c0
diff --git a/apps/optical-rest/BUCK b/apps/optical-rest/BUCK
new file mode 100644
index 0000000..9c47cb8
--- /dev/null
+++ b/apps/optical-rest/BUCK
@@ -0,0 +1,35 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:JACKSON',
+ '//lib:javax.ws.rs-api',
+ '//utils/rest:onlab-rest',
+ '//apps/optical-model:onos-apps-optical-model'
+]
+
+APPS = [
+ 'org.onosproject.optical-model',
+]
+
+TEST_DEPS = [
+ '//lib:TEST_REST',
+ '//utils/osgi:onlab-osgi-tests',
+ '//web/api:onos-rest-tests',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
+ web_context = '/onos/optical',
+ api_title = 'Optical Network Model REST API',
+ api_version = '1.0',
+ api_description = 'REST API for Optical Model',
+ api_package = 'org.onosproject.net.optical.rest'
+)
+
+onos_app (
+ title = 'Optical Network Model REST API',
+ category = 'Optical',
+ url = 'http://onosproject.org',
+ description = 'This application provides REST support for optical network model.',
+ required_apps = APPS
+)
diff --git a/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/OpticalIntentsWebResource.java b/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/OpticalIntentsWebResource.java
new file mode 100644
index 0000000..d803fe1
--- /dev/null
+++ b/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/OpticalIntentsWebResource.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.optical.rest;
+
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.optical.json.OchSignalCodec;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import static org.onosproject.net.optical.util.OpticalIntentUtility.createOpticalIntent;
+
+/**
+ * Query, submit and withdraw optical network intents.
+ */
+@Path("intents")
+public class OpticalIntentsWebResource extends AbstractWebResource {
+
+ private static final Logger log = getLogger(OpticalIntentsWebResource.class);
+
+ private static final String JSON_INVALID = "Invalid json input";
+
+ private static final String APP_ID = "appId";
+
+ private static final String INGRESS_POINT = "ingressPoint";
+ private static final String EGRESS_POINT = "egressPoint";
+
+ private static final String BIDIRECTIONAL = "bidirectional";
+
+ private static final String SIGNAL = "signal";
+
+ protected static final String MISSING_MEMBER_MESSAGE =
+ " member is required";
+ private static final String E_APP_ID_NOT_FOUND =
+ "Application ID is not found";
+
+ @Context
+ private UriInfo uriInfo;
+
+ /**
+ * Submits a new optical intent.
+ * Creates and submits optical intents from the JSON request.
+ *
+ * @param stream input JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ * @onos.rsModel CreateIntent
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createIntent(InputStream stream) {
+ try {
+ IntentService service = get(IntentService.class);
+ ObjectNode root = (ObjectNode) mapper().readTree(stream);
+ Intent intent = decode(root);
+ service.submit(intent);
+ UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
+ .path("intents")
+ .path(intent.appId().name())
+ .path(Long.toString(intent.id().fingerprint()));
+ return Response
+ .created(locationBuilder.build())
+ .build();
+ } catch (IOException ioe) {
+ throw new IllegalArgumentException(ioe);
+ }
+ }
+
+ private Intent decode(ObjectNode json) {
+ JsonNode ingressJson = json.get(INGRESS_POINT);
+ if (!ingressJson.isObject()) {
+ throw new IllegalArgumentException(JSON_INVALID);
+ }
+
+ ConnectPoint ingress = codec(ConnectPoint.class).decode((ObjectNode) ingressJson, this);
+
+ JsonNode egressJson = json.get(EGRESS_POINT);
+ if (!egressJson.isObject()) {
+ throw new IllegalArgumentException(JSON_INVALID);
+ }
+
+ ConnectPoint egress = codec(ConnectPoint.class).decode((ObjectNode) egressJson, this);
+
+ JsonNode bidirectionalJson = json.get(BIDIRECTIONAL);
+ boolean bidirectional = bidirectionalJson != null ? bidirectionalJson.asBoolean() : false;
+
+ JsonNode signalJson = json.get(SIGNAL);
+ OchSignal signal = null;
+ if (signalJson != null) {
+ if (!signalJson.isObject()) {
+ throw new IllegalArgumentException(JSON_INVALID);
+ } else {
+ signal = OchSignalCodec.decode((ObjectNode) signalJson);
+ }
+ }
+
+ String appIdString = nullIsIllegal(json.get(APP_ID), APP_ID + MISSING_MEMBER_MESSAGE).asText();
+ CoreService service = getService(CoreService.class);
+ ApplicationId appId = nullIsNotFound(service.getAppId(appIdString), E_APP_ID_NOT_FOUND);
+ Key key = null;
+ DeviceService deviceService = get(DeviceService.class);
+
+ return createOpticalIntent(ingress, egress, deviceService, key, appId, bidirectional, signal);
+ }
+}
diff --git a/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/OpticalWebApplication.java b/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/OpticalWebApplication.java
new file mode 100644
index 0000000..9dda793
--- /dev/null
+++ b/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/OpticalWebApplication.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.optical.rest;
+
+import org.onlab.rest.AbstractWebApplication;
+
+import java.util.Set;
+
+/**
+ * Optical Model Web application.
+ */
+public class OpticalWebApplication extends AbstractWebApplication {
+ @Override
+ public Set<Class<?>> getClasses() {
+ return getClasses(OpticalIntentsWebResource.class);
+ }
+}
diff --git a/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/package-info.java b/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/package-info.java
new file mode 100644
index 0000000..5cbbe16
--- /dev/null
+++ b/apps/optical-rest/src/main/java/org/onosproject/net/optical/rest/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Optical Network Model REST API.
+ */
+package org.onosproject.net.optical.rest;
diff --git a/apps/optical-rest/src/main/resources/definitions/CreateIntent.json b/apps/optical-rest/src/main/resources/definitions/CreateIntent.json
new file mode 100644
index 0000000..71ef183
--- /dev/null
+++ b/apps/optical-rest/src/main/resources/definitions/CreateIntent.json
@@ -0,0 +1,85 @@
+{
+ "type": "object",
+ "title": "createIntent",
+ "required": [
+ "ingressPoint",
+ "egressPoint"
+ ],
+ "properties": {
+ "appId": {
+ "type": "string",
+ "example": "org.onosproject.ovsdb"
+ },
+ "ingressPoint": {
+ "type": "object",
+ "title": "ingressPoint",
+ "required": [
+ "device",
+ "port"
+ ],
+ "properties": {
+ "device": {
+ "type": "string",
+ "example": "of:0000000000000001"
+ },
+ "port": {
+ "type": "string",
+ "example": "1"
+ }
+ }
+ },
+ "egressPoint": {
+ "type": "object",
+ "title": "egressPoint",
+ "required": [
+ "device",
+ "port"
+ ],
+ "properties": {
+ "device": {
+ "type": "string",
+ "example": "of:0000000000000002"
+ },
+ "port": {
+ "type": "string",
+ "example": "200"
+ }
+ }
+ },
+ "bidirection": {
+ "type": "boolean",
+ "example": true
+ },
+ "signal": {
+ "type": "object",
+ "title": "signal",
+ "required": [
+ "channelSpacing",
+ "gridType",
+ "spacingMultiplier",
+ "slotGranularity"
+ ],
+ "properties": {
+ "channelSpacing": {
+ "type": "string",
+ "example": "6.25"
+ },
+ "gridType": {
+ "type": "string",
+ "enum": ["dwdm", "cwdm", "flex"],
+ "example": "flex"
+ },
+ "spacingMultiplier": {
+ "type": "integer",
+ "format": "int32",
+ "example": 1
+ },
+ "slotGranularity": {
+ "type": "integer",
+ "format": "int32",
+ "example": 1
+ }
+ }
+ }
+ }
+}
diff --git a/apps/optical-rest/src/main/webapp/WEB-INF/web.xml b/apps/optical-rest/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..1437d86
--- /dev/null
+++ b/apps/optical-rest/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2017-present Open Networking Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ id="ONOS" version="2.5">
+ <display-name>Optical Network Model REST API</display-name>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Secured</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>admin</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-role>
+ <role-name>admin</role-name>
+ </security-role>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>karaf</realm-name>
+ </login-config>
+
+ <servlet>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.onosproject.net.optical.rest.OpticalWebApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>