ONOS-2486 Adding swagger-based REST API documentation.
Change-Id: I237d973d73549ad30ddc638c1c201f024d344c70
diff --git a/web/api/src/main/java/org/onosproject/rest/impl/ApiDocManager.java b/web/api/src/main/java/org/onosproject/rest/impl/ApiDocManager.java
new file mode 100644
index 0000000..8a31b02
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/rest/impl/ApiDocManager.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.rest.impl;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.rest.ApiDocProvider;
+import org.onosproject.rest.ApiDocService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Implementation of the REST API documentation tracker.
+ */
+@Component(immediate = true)
+@Service
+public class ApiDocManager implements ApiDocService {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ // Set of doc providers
+ private final Map<String, ApiDocProvider> providers = Maps.newConcurrentMap();
+
+ @Activate
+ public void activate() {
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public void register(ApiDocProvider provider) {
+ providers.put(provider.key(), provider);
+ }
+
+ @Override
+ public void unregister(ApiDocProvider provider) {
+ providers.remove(provider.name());
+ }
+
+ @Override
+ public Set<ApiDocProvider> getDocProviders() {
+ return ImmutableSet.copyOf(providers.values());
+ }
+
+ @Override
+ public ApiDocProvider getDocProvider(String key) {
+ return providers.get(key);
+ }
+}
diff --git a/web/api/src/main/java/org/onosproject/rest/impl/package-info.java b/web/api/src/main/java/org/onosproject/rest/impl/package-info.java
new file mode 100644
index 0000000..8fa8468
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/rest/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.
+ */
+
+/**
+ * REST API related service.
+ */
+package org.onosproject.rest.impl;
\ No newline at end of file
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/ApiDocResource.java b/web/api/src/main/java/org/onosproject/rest/resources/ApiDocResource.java
new file mode 100644
index 0000000..fa124f5
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/rest/resources/ApiDocResource.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.rest.resources;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.rest.AbstractInjectionResource;
+import org.onosproject.rest.ApiDocService;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+
+import static com.google.common.collect.ImmutableList.of;
+import static com.google.common.io.ByteStreams.toByteArray;
+import static javax.ws.rs.core.MediaType.*;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+/**
+ * REST API documentation.
+ */
+@Path("docs")
+public class ApiDocResource extends AbstractInjectionResource {
+
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final String STYLESHEET = "text/css";
+ private static final String SCRIPT = "text/javascript";
+ private static final String DOCS = "/docs/";
+
+ private static final String INJECT_START = "<!-- {API-START} -->";
+ private static final String INJECT_END = "<!-- {API-END} -->";
+
+ /**
+ * Get all registered REST API docs.
+ * Returns array of all registered API docs.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("apis")
+ public Response getApiList() {
+ ObjectNode root = mapper().createObjectNode();
+ ArrayNode apis = newArray(root, "apis");
+ get(ApiDocService.class).getDocProviders().forEach(p -> apis.add(p.name()));
+ return ok(root.toString()).build();
+ }
+
+ /**
+ * Get Swagger UI JSON.
+ *
+ * @param key REST API web context
+ * @return 200 OK
+ */
+ @GET
+ @Path("apis/{key: .*?}/swagger.json")
+ public Response getApi(@PathParam("key") String key) {
+ String k = key.startsWith("/") ? key : "/" + key;
+ InputStream stream = nullIsNotFound(get(ApiDocService.class).getDocProvider(k),
+ "REST API not found for " + k).docs();
+ return ok(nullIsNotFound(stream, "REST API docs not found for " + k))
+ .header(CONTENT_TYPE, APPLICATION_JSON).build();
+ }
+
+ /**
+ * Get REST API model schema.
+ *
+ * @param key REST API web context
+ * @return 200 OK
+ */
+ @GET
+ @Path("apis/{key: .*?}/model.json")
+ public Response getApiModel(@PathParam("name") String key) {
+ String k = key.startsWith("/") ? key : "/" + key;
+ InputStream stream = nullIsNotFound(get(ApiDocService.class).getDocProvider(k),
+ "REST API not found for " + k).model();
+ return ok(nullIsNotFound(stream, "REST API model not found for " + k))
+ .header(CONTENT_TYPE, APPLICATION_JSON).build();
+ }
+
+ /**
+ * Get Swagger UI main index page.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("/")
+ public Response getDefault() throws IOException {
+ return getIndex();
+ }
+
+ /**
+ * Get Swagger UI main index page.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("index.html")
+ public Response getIndex() throws IOException {
+ InputStream stream = getClass().getClassLoader().getResourceAsStream(DOCS + "index.html");
+ nullIsNotFound(stream, "index.html not found");
+
+ String index = new String(toByteArray(stream));
+
+ int p1s = split(index, 0, INJECT_START);
+ int p1e = split(index, p1s, INJECT_END);
+ int p2s = split(index, p1e, null);
+
+ StreamEnumeration streams =
+ new StreamEnumeration(of(stream(index, 0, p1s),
+ includeOptions(get(ApiDocService.class)),
+ stream(index, p1e, p2s)));
+
+ return ok(new SequenceInputStream(streams))
+ .header(CONTENT_TYPE, TEXT_HTML).build();
+ }
+
+ private InputStream includeOptions(ApiDocService service) {
+ StringBuilder sb = new StringBuilder();
+ service.getDocProviders().forEach(p -> {
+ sb.append("<option value=\"").append(p.key()).append("\"")
+ .append(p.key().equals("/onos/v1") ? " selected>" : ">")
+ .append(p.name())
+ .append("</option>");
+ });
+ return new ByteArrayInputStream(sb.toString().getBytes());
+ }
+
+ /**
+ * Get Swagger UI resource.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("{resource: .*}")
+ public Response getResource(@PathParam("resource") String resource) throws IOException {
+ InputStream stream = getClass().getClassLoader().getResourceAsStream(DOCS + resource);
+ return ok(nullIsNotFound(stream, resource + " not found"))
+ .header(CONTENT_TYPE, contentType(resource)).build();
+ }
+
+ static String contentType(String resource) {
+ return resource.endsWith(".html") ? TEXT_HTML :
+ resource.endsWith(".css") ? STYLESHEET :
+ resource.endsWith(".js") ? SCRIPT :
+ APPLICATION_OCTET_STREAM;
+ }
+}
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java
index 91148db..636fc33 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java
@@ -35,32 +35,54 @@
import java.util.Set;
/**
- * REST resource for interacting with the inventory of applications.
+ * Manage inventory of applications.
*/
@Path("applications")
public class ApplicationsWebResource extends AbstractWebResource {
+ /**
+ * Get all installed applications.
+ * Returns array of all installed applications.
+ *
+ * @return 200 OK
+ */
@GET
- public Response getApplications() {
+ public Response getApps() {
ApplicationAdminService service = get(ApplicationAdminService.class);
Set<Application> apps = service.getApplications();
return ok(encodeArray(Application.class, "applications", apps)).build();
}
+ /**
+ * Get application details.
+ * Returns details of the specified application.
+ *
+ * @param name application name
+ * @return 200 OK; 404; 401
+ */
@GET
@Path("{name}")
- public Response getApplication(@PathParam("name") String name) {
+ public Response getApp(@PathParam("name") String name) {
ApplicationAdminService service = get(ApplicationAdminService.class);
ApplicationId appId = service.getId(name);
return response(service, appId);
}
+ /**
+ * Install a new application.
+ * Uploads application archive stream and optionally activates the
+ * application.
+ *
+ * @param activate true to activate app also
+ * @param stream application archive stream
+ * @return 200 OK; 404; 401
+ */
@POST
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_JSON)
- public Response installApplication(@QueryParam("activate")
- @DefaultValue("false") boolean activate,
- InputStream stream) {
+ public Response installApp(@QueryParam("activate")
+ @DefaultValue("false") boolean activate,
+ InputStream stream) {
ApplicationAdminService service = get(ApplicationAdminService.class);
Application app = service.install(stream);
if (activate) {
@@ -69,30 +91,51 @@
return ok(codec(Application.class).encode(app, this)).build();
}
+ /**
+ * Uninstall application.
+ * Uninstalls the specified application deactivating it first if necessary.
+ *
+ * @param name application name
+ * @return 200 OK; 404; 401
+ */
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Path("{name}")
- public Response uninstallApplication(@PathParam("name") String name) {
+ public Response uninstallApp(@PathParam("name") String name) {
ApplicationAdminService service = get(ApplicationAdminService.class);
ApplicationId appId = service.getId(name);
service.uninstall(appId);
return Response.ok().build();
}
+ /**
+ * Activate application.
+ * Activates the specified application.
+ *
+ * @param name application name
+ * @return 200 OK; 404; 401
+ */
@POST
@Produces(MediaType.APPLICATION_JSON)
@Path("{name}/active")
- public Response activateApplication(@PathParam("name") String name) {
+ public Response activateApp(@PathParam("name") String name) {
ApplicationAdminService service = get(ApplicationAdminService.class);
ApplicationId appId = service.getId(name);
service.activate(appId);
return response(service, appId);
}
+ /**
+ * De-activate application.
+ * De-activates the specified application.
+ *
+ * @param name application name
+ * @return 200 OK; 404; 401
+ */
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Path("{name}/active")
- public Response deactivateApplication(@PathParam("name") String name) {
+ public Response deactivateApp(@PathParam("name") String name) {
ApplicationAdminService service = get(ApplicationAdminService.class);
ApplicationId appId = service.getId(name);
service.deactivate(appId);
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java
index 690637e..ee608b7 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java
@@ -37,19 +37,32 @@
import static org.onlab.util.Tools.nullIsNotFound;
/**
- * REST resource for interacting with the ONOS cluster subsystem.
+ * Manage cluster of ONOS instances.
*/
@Path("cluster")
public class ClusterWebResource extends AbstractWebResource {
public static final String NODE_NOT_FOUND = "Node is not found";
+ /**
+ * Get all cluster nodes.
+ * Returns array of all cluster nodes.
+ *
+ * @return 200 OK
+ */
@GET
public Response getClusterNodes() {
Iterable<ControllerNode> nodes = get(ClusterService.class).getNodes();
return ok(encodeArray(ControllerNode.class, "nodes", nodes)).build();
}
+ /**
+ * Get cluster node details.
+ * Returns details of the specified cluster node.
+ *
+ * @param id cluster node identifier
+ * @return 200 OK
+ */
@GET
@Path("{id}")
public Response getClusterNode(@PathParam("id") String id) {
@@ -58,6 +71,13 @@
return ok(codec(ControllerNode.class).encode(node, this)).build();
}
+ /**
+ * Forms cluster of ONOS instances.
+ * Forms ONOS cluster using the uploaded JSON definition.
+ *
+ * @param config cluster definition
+ * @return 200 OK
+ */
@POST
@Path("configuration")
public Response formCluster(InputStream config) throws IOException {
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/ComponentConfigWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/ComponentConfigWebResource.java
index 1155be2..4adb6c5 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/ComponentConfigWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/ComponentConfigWebResource.java
@@ -33,11 +33,17 @@
import static org.onlab.util.Tools.nullIsNotFound;
/**
- * REST resource for cluster-wide component configuration.
+ * Manage component configurations.
*/
@Path("configuration")
public class ComponentConfigWebResource extends AbstractWebResource {
+ /**
+ * Get all component configurations.
+ * Returns collection of all registered component configurations.
+ *
+ * @return 200 OK
+ */
@GET
public Response getComponentConfigs() {
ComponentConfigService service = get(ComponentConfigService.class);
@@ -47,6 +53,12 @@
return ok(root).build();
}
+ /**
+ * Get configuration of the specified component.
+ *
+ * @param component component name
+ * @return 200 OK
+ */
@GET
@Path("{component}")
public Response getComponentConfigs(@PathParam("component") String component) {
@@ -65,10 +77,17 @@
props.forEach(p -> compNode.put(p.name(), p.value()));
}
+ /**
+ * Selectively set configuration properties.
+ * Sets only the properties present in the JSON request.
+ *
+ * @param component component name
+ * @return 200 OK
+ */
@POST
@Path("{component}")
- public Response setComponentConfigs(@PathParam("component") String component,
- InputStream request) throws IOException {
+ public Response setConfigs(@PathParam("component") String component,
+ InputStream request) throws IOException {
ComponentConfigService service = get(ComponentConfigService.class);
ObjectNode props = (ObjectNode) mapper().readTree(request);
props.fieldNames().forEachRemaining(k -> service.setProperty(component, k,
@@ -76,10 +95,17 @@
return Response.noContent().build();
}
+ /**
+ * Selectively clear configuration properties.
+ * Clears only the properties present in the JSON request.
+ *
+ * @param component component name
+ * @return 200 OK
+ */
@DELETE
@Path("{component}")
- public Response unsetComponentConfigs(@PathParam("component") String component,
- InputStream request) throws IOException {
+ public Response unsetConfigs(@PathParam("component") String component,
+ InputStream request) throws IOException {
ComponentConfigService service = get(ComponentConfigService.class);
ObjectNode props = (ObjectNode) mapper().readTree(request);
props.fieldNames().forEachRemaining(k -> service.unsetProperty(component, k));
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/ConfigWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/ConfigWebResource.java
index 746b76a..b0db475 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/ConfigWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/ConfigWebResource.java
@@ -37,14 +37,20 @@
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
/**
- * Resource that acts as an ancillary provider for uploading pre-configured
- * devices, ports and links.
+ * Inject devices, ports, links and end-station hosts.
*/
@Path("config")
public class ConfigWebResource extends BaseResource {
private static Logger log = LoggerFactory.getLogger(ConfigWebResource.class);
+ /**
+ * Upload device, port, link and host data.
+ *
+ * @param input JSON blob
+ * @return 200 OK
+ * @throws IOException
+ */
@POST
@Path("topology")
@Consumes(MediaType.APPLICATION_JSON)
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java
index 1604752..05756e5 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java
@@ -34,19 +34,32 @@
import static org.onosproject.net.DeviceId.deviceId;
/**
- * REST resource for interacting with the inventory of infrastructure devices.
+ * Manage inventory of infrastructure devices.
*/
@Path("devices")
public class DevicesWebResource extends AbstractWebResource {
public static final String DEVICE_NOT_FOUND = "Device is not found";
+ /**
+ * Get all infrastructure devices.
+ * Returns array of all discovered infrastructure devices.
+ *
+ * @return 200 OK
+ */
@GET
public Response getDevices() {
Iterable<Device> devices = get(DeviceService.class).getDevices();
return ok(encodeArray(Device.class, "devices", devices)).build();
}
+ /**
+ * Get details of infrastructure device.
+ * Returns details of the specified infrastructure device.
+ *
+ * @param id device identifier
+ * @return 200 OK
+ */
@GET
@Path("{id}")
public Response getDevice(@PathParam("id") String id) {
@@ -55,6 +68,14 @@
return ok(codec(Device.class).encode(device, this)).build();
}
+ /**
+ * Remove infrastructure device.
+ * Administratively deletes the specified device from the inventory of
+ * known devices.
+ *
+ * @param id device identifier
+ * @return 200 OK
+ */
@DELETE
@Path("{id}")
public Response removeDevice(@PathParam("id") String id) {
@@ -64,6 +85,13 @@
return ok(codec(Device.class).encode(device, this)).build();
}
+ /**
+ * Get ports of infrastructure device.
+ * Returns details of the specified infrastructure device.
+ *
+ * @param id device identifier
+ * @return 200 OK
+ */
@GET
@Path("{id}/ports")
public Response getDevicePorts(@PathParam("id") String id) {
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java
index 45529a4..325e191 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java
@@ -45,7 +45,7 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
- * REST resource for interacting with the inventory of flows.
+ * Query and program flow rules.
*/
@Path("flows")
@@ -57,14 +57,13 @@
final ArrayNode flowsNode = root.putArray("flows");
/**
- * Gets an array containing all the intents in the system.
+ * Get all flow entries. Returns array of all flow rules in the system.
*
* @return array of all the intents in the system
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getFlows() {
-
final Iterable<Device> devices = get(DeviceService.class).getDevices();
for (final Device device : devices) {
final Iterable<FlowEntry> deviceEntries = service.getFlowEntries(device.id());
@@ -79,9 +78,10 @@
}
/**
- * Gets the flows for a device, where the device is specified by Id.
+ * Get flow entries of a device. Returns array of all flow rules for the
+ * specified device.
*
- * @param deviceId Id of device to look up
+ * @param deviceId device identifier
* @return flow data as an array
*/
@GET
@@ -101,10 +101,11 @@
}
/**
- * Gets the flows for a device, where the device is specified by Id.
+ * Get flow rule. Returns the flow entry specified by the device id and
+ * flow rule id.
*
- * @param deviceId Id of device to look up
- * @param flowId Id of flow to look up
+ * @param deviceId device identifier
+ * @param flowId flow rule identifier
* @return flow data as an array
*/
@GET
@@ -127,10 +128,11 @@
}
/**
- * Creates a flow rule from a POST of a JSON string and attempts to apply it.
+ * Create new flow rule. Creates and installs a new flow rule for the
+ * specified device.
*
* @param deviceId device identifier
- * @param stream input JSON
+ * @param stream flow rule JSON
* @return status of the request - CREATED if the JSON is correct,
* BAD_REQUEST if the JSON is invalid
*/
@@ -163,16 +165,16 @@
}
/**
- * Removes the flows for a given device with the given flow id.
+ * Remove flow rule. Removes the specified flow rule.
*
- * @param deviceId Id of device to look up
- * @param flowId Id of flow to look up
+ * @param deviceId device identifier
+ * @param flowId flow rule identifier
*/
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Path("{deviceId}/{flowId}")
public void deleteFlowByDeviceIdAndFlowId(@PathParam("deviceId") String deviceId,
- @PathParam("flowId") long flowId) {
+ @PathParam("flowId") long flowId) {
final Iterable<FlowEntry> deviceEntries =
service.getFlowEntries(DeviceId.deviceId(deviceId));
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java
index 9d3fd7f..b89f5ad 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java
@@ -56,7 +56,7 @@
import static org.onosproject.net.HostId.hostId;
/**
- * REST resource for interacting with the inventory of hosts.
+ * Manage inventory of end-station hosts.
*/
@Path("hosts")
public class HostsWebResource extends AbstractWebResource {
@@ -65,6 +65,12 @@
UriInfo uriInfo;
public static final String HOST_NOT_FOUND = "Host is not found";
+ /**
+ * Get all end-station hosts.
+ * Returns array of all known end-station hosts.
+ *
+ * @return 200 OK
+ */
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getHosts() {
@@ -73,6 +79,13 @@
return ok(root).build();
}
+ /**
+ * Get details of end-station host.
+ * Returns detailed properties of the specified end-station host.
+ *
+ * @param id host identifier
+ * @return 200 OK
+ */
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}")
@@ -83,6 +96,14 @@
return ok(root).build();
}
+ /**
+ * Get details of end-station host with MAC/VLAN.
+ * Returns detailed properties of the specified end-station host.
+ *
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @return 200 OK
+ */
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{mac}/{vlan}")
@@ -157,6 +178,7 @@
/**
* Creates and adds new host based on given data and returns its host ID.
+ *
* @param node JsonNode containing host information
* @return host ID of new host created
*/
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java
index 09fdd2f..b29e3e8 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java
@@ -55,9 +55,8 @@
import static org.slf4j.LoggerFactory.getLogger;
/**
- * REST resource for interacting with the inventory of intents.
+ * Query, submit and withdraw network intents.
*/
-
@Path("intents")
public class IntentsWebResource extends AbstractWebResource {
@Context
@@ -69,7 +68,8 @@
public static final String INTENT_NOT_FOUND = "Intent is not found";
/**
- * Gets an array containing all the intents in the system.
+ * Get all intents.
+ * Returns array containing all the intents in the system.
*
* @return array of all the intents in the system
*/
@@ -82,10 +82,11 @@
}
/**
- * Gets a single intent by Id.
+ * Get intent by application and key.
+ * Returns details of the specified intent.
*
- * @param appId the Application ID
- * @param key the Intent key value to look up
+ * @param appId application identifier
+ * @param key intent key
* @return intent data
*/
@GET
@@ -125,70 +126,16 @@
@Override
public void event(IntentEvent event) {
if (Objects.equals(event.subject().key(), key) &&
- (event.type() == IntentEvent.Type.WITHDRAWN ||
- event.type() == IntentEvent.Type.FAILED)) {
+ (event.type() == IntentEvent.Type.WITHDRAWN ||
+ event.type() == IntentEvent.Type.FAILED)) {
latch.countDown();
}
}
}
/**
- * Uninstalls a single intent by Id.
- *
- * @param appId the Application ID
- * @param keyString the Intent key value to look up
- */
- @DELETE
- @Path("{appId}/{key}")
- public void deleteIntentById(@PathParam("appId") String appId,
- @PathParam("key") String keyString) {
- final ApplicationId app = get(CoreService.class).getAppId(appId);
-
- Intent intent = get(IntentService.class).getIntent(Key.of(keyString, app));
- IntentService service = get(IntentService.class);
-
- if (intent == null) {
- intent = service
- .getIntent(Key.of(Long.decode(keyString), app));
- }
- if (intent == null) {
- // No such intent. REST standards recommend a positive status code
- // in this case.
- return;
- }
-
-
- Key key = intent.key();
-
- // set up latch and listener to track uninstall progress
- CountDownLatch latch = new CountDownLatch(1);
-
- IntentListener listener = new DeleteListener(key, latch);
- service.addListener(listener);
-
- try {
- // request the withdraw
- service.withdraw(intent);
-
- try {
- latch.await(WITHDRAW_EVENT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- log.info("REST Delete operation timed out waiting for intent {}", key);
- }
- // double check the state
- IntentState state = service.getIntentState(key);
- if (state == WITHDRAWN || state == FAILED) {
- service.purge(intent);
- }
-
- } finally {
- // clean up the listener
- service.removeListener(listener);
- }
- }
-
- /**
- * Creates an intent from a POST of a JSON string and attempts to apply it.
+ * Submit a new intent.
+ * Creates and submits intent from the JSON request.
*
* @param stream input JSON
* @return status of the request - CREATED if the JSON is correct,
@@ -215,4 +162,60 @@
}
}
+ /**
+ * Withdraw intent.
+ * Withdraws the specified intent from the system.
+ *
+ * @param appId application identifier
+ * @param key intent key
+ */
+ @DELETE
+ @Path("{appId}/{key}")
+ public void deleteIntentById(@PathParam("appId") String appId,
+ @PathParam("key") String key) {
+ final ApplicationId app = get(CoreService.class).getAppId(appId);
+
+ Intent intent = get(IntentService.class).getIntent(Key.of(key, app));
+ IntentService service = get(IntentService.class);
+
+ if (intent == null) {
+ intent = service
+ .getIntent(Key.of(Long.decode(key), app));
+ }
+ if (intent == null) {
+ // No such intent. REST standards recommend a positive status code
+ // in this case.
+ return;
+ }
+
+
+ Key k = intent.key();
+
+ // set up latch and listener to track uninstall progress
+ CountDownLatch latch = new CountDownLatch(1);
+
+ IntentListener listener = new DeleteListener(k, latch);
+ service.addListener(listener);
+
+ try {
+ // request the withdraw
+ service.withdraw(intent);
+
+ try {
+ latch.await(WITHDRAW_EVENT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ log.info("REST Delete operation timed out waiting for intent {}", k);
+ }
+ // double check the state
+ IntentState state = service.getIntentState(k);
+ if (state == WITHDRAWN || state == FAILED) {
+ service.purge(intent);
+ }
+
+ } finally {
+ // clean up the listener
+ service.removeListener(listener);
+ }
+ }
+
}
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java
index 1922d03..c627019 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java
@@ -30,7 +30,7 @@
import static org.onosproject.net.PortNumber.portNumber;
/**
- * REST resource for interacting with the inventory of infrastructure links.
+ * Manage inventory of infrastructure links.
*/
@Path("links")
public class LinksWebResource extends AbstractWebResource {
@@ -41,6 +41,15 @@
EGRESS
}
+ /**
+ * Get infrastructure links.
+ * Returns array of all links, or links for the specified device or port.
+ *
+ * @param deviceId (optional) device identifier
+ * @param port (optional) port number
+ * @param direction (optional) direction qualifier
+ * @return 200 OK
+ */
@GET
public Response getLinks(@QueryParam("device") String deviceId,
@QueryParam("port") String port,
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java
index 348fa63..9e2b627 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java
@@ -33,13 +33,13 @@
import java.io.InputStream;
/**
- * REST resource for injecting and retrieving common network configuration.
+ * Manage network configurations.
*/
@Path("network/configuration")
public class NetworkConfigWebResource extends AbstractWebResource {
/**
- * Returns entire network configuration base.
+ * Get entire network configuration base.
*
* @return network configuration JSON
*/
@@ -55,7 +55,7 @@
}
/**
- * Returns the network configuration for the specified subject class.
+ * Get all network configuration for a subject class.
*
* @param subjectKey subject class key
* @return network configuration JSON
@@ -72,7 +72,7 @@
}
/**
- * Returns the network configuration for the specified subject.
+ * Get all network configuration for a subject.
*
* @param subjectKey subject class key
* @param subject subject key
@@ -87,13 +87,12 @@
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = mapper().createObjectNode();
produceSubjectJson(service, root,
- service.getSubjectFactory(subjectKey).createSubject(subject));
+ service.getSubjectFactory(subjectKey).createSubject(subject));
return ok(root).build();
}
/**
- * Returns the network configuration for the specified subject and given
- * configuration class.
+ * Get specific network configuration for a subject.
*
* @param subjectKey subject class key
* @param subject subject key
@@ -126,7 +125,7 @@
/**
- * Uploads network configuration in bulk.
+ * Upload bulk network configuration.
*
* @param request network configuration JSON rooted at the top node
* @throws IOException if unable to parse the request
@@ -140,12 +139,12 @@
ObjectNode root = (ObjectNode) mapper().readTree(request);
root.fieldNames()
.forEachRemaining(sk -> consumeJson(service, (ObjectNode) root.path(sk),
- service.getSubjectFactory(sk)));
+ service.getSubjectFactory(sk)));
return Response.ok().build();
}
/**
- * Uploads network configuration for the specified subject class.
+ * Upload multiple network configurations for a subject class.
*
* @param subjectKey subject class key
* @param request network configuration JSON rooted at the top node
@@ -165,7 +164,7 @@
}
/**
- * Uploads network configuration for the specified subject.
+ * Upload mutliple network configurations for a subject.
*
* @param subjectKey subject class key
* @param subject subject key
@@ -183,14 +182,13 @@
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = (ObjectNode) mapper().readTree(request);
consumeSubjectJson(service, root,
- service.getSubjectFactory(subjectKey).createSubject(subject),
- subjectKey);
+ service.getSubjectFactory(subjectKey).createSubject(subject),
+ subjectKey);
return Response.ok().build();
}
/**
- * Uploads network configuration for the specified subject and given
- * configuration class.
+ * Upload specific network configuration for a subject.
*
* @param subjectKey subject class key
* @param subject subject key
@@ -210,16 +208,16 @@
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = (ObjectNode) mapper().readTree(request);
service.applyConfig(service.getSubjectFactory(subjectKey).createSubject(subject),
- service.getConfigClass(subjectKey, configKey), root);
+ service.getConfigClass(subjectKey, configKey), root);
return Response.ok().build();
}
private void consumeJson(NetworkConfigService service, ObjectNode classNode,
SubjectFactory subjectFactory) {
classNode.fieldNames().forEachRemaining(s ->
- consumeSubjectJson(service, (ObjectNode) classNode.path(s),
- subjectFactory.createSubject(s),
- subjectFactory.subjectKey()));
+ consumeSubjectJson(service, (ObjectNode) classNode.path(s),
+ subjectFactory.createSubject(s),
+ subjectFactory.subjectKey()));
}
private void consumeSubjectJson(NetworkConfigService service,
@@ -227,12 +225,47 @@
String subjectKey) {
subjectNode.fieldNames().forEachRemaining(c ->
service.applyConfig(subject, service.getConfigClass(subjectKey, c),
- (ObjectNode) subjectNode.path(c)));
+ (ObjectNode) subjectNode.path(c)));
}
/**
- * Clears network configuration for the specified subject.
+ * Clear entire network configuration base.
+ *
+ * @return empty response
+ */
+ @DELETE
+ @SuppressWarnings("unchecked")
+ public Response delete() {
+ NetworkConfigService service = get(NetworkConfigService.class);
+ service.getSubjectClasses()
+ .forEach(subjectClass -> service.getSubjects(subjectClass)
+ .forEach(subject -> service.getConfigs(subject)
+ .forEach(config -> service
+ .removeConfig(subject, config.getClass()))));
+ return Response.ok().build();
+ }
+
+ /**
+ * Clear all network configurations for a subject class.
+ *
+ * @param subjectKey subject class key
+ * @return empty response
+ */
+ @DELETE
+ @Path("{subjectKey}")
+ @SuppressWarnings("unchecked")
+ public Response delete(@PathParam("subjectKey") String subjectKey) {
+ NetworkConfigService service = get(NetworkConfigService.class);
+ service.getSubjects(service.getSubjectFactory(subjectKey).getClass())
+ .forEach(subject -> service.getConfigs(subject)
+ .forEach(config -> service
+ .removeConfig(subject, config.getClass())));
+ return Response.ok().build();
+ }
+
+ /**
+ * Clear all network configurations for a subject.
*
* @param subjectKey subject class key
* @param subject subject key
@@ -250,8 +283,7 @@
}
/**
- * Clears network configuration for the specified subject and given
- * configuration class.
+ * Clear specific network configuration for a subject.
*
* @param subjectKey subject class key
* @param subject subject key
@@ -266,45 +298,8 @@
@PathParam("configKey") String configKey) {
NetworkConfigService service = get(NetworkConfigService.class);
service.removeConfig(service.getSubjectFactory(subjectKey).createSubject(subject),
- service.getConfigClass(subjectKey, configKey));
+ service.getConfigClass(subjectKey, configKey));
return Response.ok().build();
}
-
- /**
- * Clears all network configurations.
- *
- * @return empty response
- */
- @DELETE
- @SuppressWarnings("unchecked")
- public Response delete() {
- NetworkConfigService service = get(NetworkConfigService.class);
- service.getSubjectClasses()
- .forEach(subjectClass -> service.getSubjects(subjectClass)
- .forEach(subject -> service.getConfigs(subject)
- .forEach(config -> service
- .removeConfig(subject, config.getClass()))));
- return Response.ok().build();
- }
-
-
- // TODO: this one below doesn't work correctly
- /**
- * Clears network configuration for the specified subject class.
- *
- * @param subjectKey subject class key
- * @return empty response
- */
- @DELETE
- @Path("{subjectKey}/")
- @SuppressWarnings("unchecked")
- public Response delete(@PathParam("subjectKey") String subjectKey) {
- NetworkConfigService service = get(NetworkConfigService.class);
- service.getSubjects(service.getSubjectFactory(subjectKey).getClass())
- .forEach(subject -> service.getConfigs(subject)
- .forEach(config -> service
- .removeConfig(subject, config.getClass())));
- return Response.ok().build();
- }
}
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java
index 42bd4e1..baa1b1e 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java
@@ -33,7 +33,7 @@
import org.onosproject.rest.AbstractWebResource;
/**
- * REST resource for interacting with path calculations.
+ * Compute paths in the network graph.
*/
@Path("paths")
public class PathsWebResource extends AbstractWebResource {
@@ -46,19 +46,15 @@
* @return HostId if the id is valid, null otherwise
*/
private HostId isHostId(String id) {
-
- if (!id.matches("..:..:..:..:..:../.*")) {
- return null;
- }
-
- return HostId.hostId(id);
+ return id.matches("..:..:..:..:..:../.*") ? HostId.hostId(id) : null;
}
/**
- * Gets the paths between two elements.
+ * Get all shortest paths between any two hosts or devices.
+ * Returns array of all shortest paths between any two elements.
*
- * @param src source
- * @param dst destination
+ * @param src source identifier
+ * @param dst destination identifier
* @return path data
*/
@GET
@@ -81,10 +77,8 @@
dstElement = DeviceId.deviceId(dst);
}
- Set<org.onosproject.net.Path> paths =
- pathService.getPaths(srcElement, dstElement);
- ObjectNode root =
- encodeArray(org.onosproject.net.Path.class, "paths", paths);
+ Set<org.onosproject.net.Path> paths = pathService.getPaths(srcElement, dstElement);
+ ObjectNode root = encodeArray(org.onosproject.net.Path.class, "paths", paths);
return ok(root).build();
}
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java
index 36bb0ad..2ffa229 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java
@@ -44,7 +44,7 @@
import static org.onosproject.net.PortNumber.portNumber;
/**
- * Statistics REST APIs.
+ * Query flow statistics.
*/
@Path("statistics")
public class StatisticsWebResource extends AbstractWebResource {
@@ -52,7 +52,7 @@
UriInfo uriInfo;
/**
- * Gets the Load statistics for all links, or for a specific link.
+ * Get load statistics for all links or for a specific link.
*
* @param deviceId (optional) device ID for a specific link
* @param port (optional) port number for a specified link
@@ -77,7 +77,6 @@
JsonCodec<Load> loadCodec = codec(Load.class);
StatisticService statsService = getService(StatisticService.class);
-
StreamSupport.stream(Spliterators.spliteratorUnknownSize(
links.iterator(), Spliterator.ORDERED), false)
.forEach(link -> {
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java
index 55b6803..f6ae825 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java
@@ -39,16 +39,15 @@
import static org.onlab.util.Tools.nullIsNotFound;
/**
- * REST resource for interacting with the inventory of clusters.
+ * Query network topology graph and its components.
*/
-
@Path("topology")
public class TopologyWebResource extends AbstractWebResource {
public static final String CLUSTER_NOT_FOUND = "Cluster is not found";
/**
- * Gets the topology overview for a REST GET operation.
+ * Get overview of current topology.
*
* @return topology overview
*/
@@ -61,7 +60,7 @@
}
/**
- * Gets the topology clusters overview for a REST GET operation.
+ * Get overview of topology SCCs.
*
* @return topology clusters overview
*/
@@ -77,7 +76,7 @@
}
/**
- * Gets details for a topology cluster for a REST GET operation.
+ * Get details of a specific SCC.
*
* @param clusterId id of the cluster to query
* @return topology cluster details
@@ -100,7 +99,7 @@
}
/**
- * Gets devices for a topology cluster for a REST GET operation.
+ * Get devices in a specific SCC.
*
* @param clusterId id of the cluster to query
* @return topology cluster devices
@@ -123,7 +122,7 @@
}
/**
- * Gets links for a topology cluster for a REST GET operation.
+ * Get links in specific SCC.
*
* @param clusterId id of the cluster to query
* @return topology cluster links
@@ -171,18 +170,16 @@
}
/**
- * Gets the broadcast flag of a connect point for a REST GET operation.
+ * Test if a connect point is in broadcast set.
*
- * @param connectPointString string representation of the connect point to query.
- * Format is deviceid:portnumber
+ * @param connectPointString deviceid:portnumber
* @return JSON representation of true if the connect point is broadcast,
* false otherwise
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("broadcast/{connectPoint}")
- public Response getConnectPointBroadcast(
- @PathParam("connectPoint") String connectPointString) {
+ public Response getConnectPointBroadcast(@PathParam("connectPoint") String connectPointString) {
Topology topology = get(TopologyService.class).currentTopology();
DeviceId deviceId = DeviceId.deviceId(getDeviceId(connectPointString));
@@ -197,18 +194,16 @@
}
/**
- * Gets the infrastructure flag of a connect point for a REST GET operation.
+ * Test if a connect point is infrastructure or edge.
*
- * @param connectPointString string representation of the connect point to query.
- * Format is deviceid:portnumber
+ * @param connectPointString deviceid:portnumber
* @return JSON representation of true if the connect point is broadcast,
* false otherwise
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("infrastructure/{connectPoint}")
- public Response getConnectPointInfrastructure(
- @PathParam("connectPoint") String connectPointString) {
+ public Response getConnectPointInfrastructure(@PathParam("connectPoint") String connectPointString) {
Topology topology = get(TopologyService.class).currentTopology();
DeviceId deviceId = DeviceId.deviceId(getDeviceId(connectPointString));