blob: c17683cbb5f091d014bf5ba1e735d5d19e92b4ab [file] [log] [blame]
Jian Li0c451802016-02-24 22:39:25 +09001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Jian Li0c451802016-02-24 22:39:25 +09003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.rest.resources;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import com.google.common.collect.Sets;
22import org.onosproject.net.DeviceId;
23import org.onosproject.net.region.Region;
24import org.onosproject.net.region.RegionAdminService;
25import org.onosproject.net.region.RegionId;
26import org.onosproject.net.region.RegionService;
27import org.onosproject.rest.AbstractWebResource;
28
29import javax.ws.rs.Consumes;
30import javax.ws.rs.DELETE;
31import javax.ws.rs.GET;
32import javax.ws.rs.POST;
33import javax.ws.rs.PUT;
34import javax.ws.rs.Path;
35import javax.ws.rs.PathParam;
36import javax.ws.rs.Produces;
37import javax.ws.rs.core.MediaType;
38import javax.ws.rs.core.Response;
39import java.io.IOException;
40import java.io.InputStream;
41import java.net.URI;
42import java.net.URISyntaxException;
43import java.util.Set;
44
45import static org.onlab.util.Tools.nullIsNotFound;
46
47/**
48 * Manages region and device membership.
49 */
50@Path("regions")
51public class RegionsWebResource extends AbstractWebResource {
52 private final RegionService regionService = get(RegionService.class);
53 private final RegionAdminService regionAdminService = get(RegionAdminService.class);
54
55 private static final String REGION_NOT_FOUND = "Region is not found for ";
56 private static final String REGION_INVALID = "Invalid regionId in region update request";
57 private static final String DEVICE_IDS_INVALID = "Invalid device identifiers";
58
59 /**
60 * Returns set of all regions.
61 *
Jian Licc730a62016-05-10 16:36:16 -070062 * @return 200 OK with set of all regions
Jian Li0c451802016-02-24 22:39:25 +090063 * @onos.rsModel Regions
64 */
65 @GET
66 @Produces(MediaType.APPLICATION_JSON)
67 public Response getRegions() {
68 final Iterable<Region> regions = regionService.getRegions();
69 return ok(encodeArray(Region.class, "regions", regions)).build();
70 }
71
72 /**
73 * Returns the region with the specified identifier.
74 *
75 * @param regionId region identifier
Jian Licc730a62016-05-10 16:36:16 -070076 * @return 200 OK with a region, 404 not found
Jian Li0c451802016-02-24 22:39:25 +090077 * @onos.rsModel Region
78 */
79 @GET
80 @Produces(MediaType.APPLICATION_JSON)
81 @Path("{regionId}")
82 public Response getRegionById(@PathParam("regionId") String regionId) {
83 final RegionId rid = RegionId.regionId(regionId);
84 final Region region = nullIsNotFound(regionService.getRegion(rid),
85 REGION_NOT_FOUND + rid.toString());
86 return ok(codec(Region.class).encode(region, this)).build();
87 }
88
89 /**
90 * Returns the set of devices that belong to the specified region.
91 *
92 * @param regionId region identifier
Jian Licc730a62016-05-10 16:36:16 -070093 * @return 200 OK with set of devices that belong to the specified region
Jian Li0c451802016-02-24 22:39:25 +090094 * @onos.rsModel RegionDeviceIds
95 */
96 @GET
97 @Produces(MediaType.APPLICATION_JSON)
98 @Path("{regionId}/devices")
99 public Response getRegionDevices(@PathParam("regionId") String regionId) {
100 final RegionId rid = RegionId.regionId(regionId);
101 final Iterable<DeviceId> deviceIds = regionService.getRegionDevices(rid);
102 final ObjectNode root = mapper().createObjectNode();
103 final ArrayNode deviceIdsNode = root.putArray("deviceIds");
104 deviceIds.forEach(did -> deviceIdsNode.add(did.toString()));
105 return ok(root).build();
106 }
107
108 /**
109 * Creates a new region using the supplied JSON input stream.
110 *
111 * @param stream region JSON stream
112 * @return status of the request - CREATED if the JSON is correct,
113 * BAD_REQUEST if the JSON is invalid
114 * @onos.rsModel RegionPost
115 */
116 @POST
117 @Consumes(MediaType.APPLICATION_JSON)
118 @Produces(MediaType.APPLICATION_JSON)
119 public Response createRegion(InputStream stream) {
120 URI location;
121 try {
122 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
123 final Region region = codec(Region.class).decode(jsonTree, this);
124 final Region resultRegion = regionAdminService.createRegion(region.id(),
125 region.name(), region.type(), region.masters());
126 location = new URI(resultRegion.id().id());
127 } catch (IOException | URISyntaxException e) {
128 throw new IllegalArgumentException(e);
129 }
130
131 return Response.created(location).build();
132 }
133
134 /**
135 * Updates the specified region using the supplied JSON input stream.
136 *
137 * @param regionId region identifier
138 * @param stream region JSON stream
139 * @return status of the request - UPDATED if the JSON is correct,
140 * BAD_REQUEST if the JSON is invalid
141 * @onos.rsModel RegionPost
142 */
143 @PUT
144 @Path("{regionId}")
145 @Consumes(MediaType.APPLICATION_JSON)
Jian Li0c451802016-02-24 22:39:25 +0900146 public Response updateRegion(@PathParam("regionId") String regionId,
147 InputStream stream) {
148 try {
149 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
150 JsonNode specifiedRegionId = jsonTree.get("id");
151
152 if (specifiedRegionId != null &&
153 !specifiedRegionId.asText().equals(regionId)) {
154 throw new IllegalArgumentException(REGION_INVALID);
155 }
156
157 final Region region = codec(Region.class).decode(jsonTree, this);
158 regionAdminService.updateRegion(region.id(),
159 region.name(), region.type(), region.masters());
160 } catch (IOException e) {
161 throw new IllegalArgumentException(e);
162 }
163
164 return Response.ok().build();
165 }
166
167 /**
168 * Removes the specified region using the given region identifier.
169 *
170 * @param regionId region identifier
Jian Licc730a62016-05-10 16:36:16 -0700171 * @return 204 NO CONTENT
Jian Li0c451802016-02-24 22:39:25 +0900172 */
173 @DELETE
174 @Path("{regionId}")
Jian Li0c451802016-02-24 22:39:25 +0900175 public Response removeRegion(@PathParam("regionId") String regionId) {
176 final RegionId rid = RegionId.regionId(regionId);
177 regionAdminService.removeRegion(rid);
Jian Lic2a542b2016-05-10 11:48:19 -0700178 return Response.noContent().build();
Jian Li0c451802016-02-24 22:39:25 +0900179 }
180
181 /**
182 * Adds the specified collection of devices to the region.
183 *
184 * @param regionId region identifier
185 * @param stream deviceIds JSON stream
186 * @return status of the request - CREATED if the JSON is correct,
187 * BAD_REQUEST if the JSON is invalid
188 * @onos.rsModel RegionDeviceIds
189 */
190 @POST
191 @Path("{regionId}/devices")
192 @Consumes(MediaType.APPLICATION_JSON)
193 @Produces(MediaType.APPLICATION_JSON)
194 public Response addDevices(@PathParam("regionId") String regionId,
195 InputStream stream) {
196 final RegionId rid = RegionId.regionId(regionId);
197
198 URI location;
199 try {
200 regionAdminService.addDevices(rid, extractDeviceIds(stream));
201 location = new URI(rid.id());
202 } catch (IOException | URISyntaxException e) {
203 throw new IllegalArgumentException(e);
204 }
205
206 return Response.created(location).build();
207 }
208
209 /**
210 * Removes the specified collection of devices from the region.
211 *
212 * @param regionId region identifier
213 * @param stream deviceIds JSON stream
Jian Lic2a542b2016-05-10 11:48:19 -0700214 * @return 204 NO CONTENT
Jian Li0c451802016-02-24 22:39:25 +0900215 * @onos.rsModel RegionDeviceIds
216 */
217 @DELETE
218 @Path("{regionId}/devices")
219 @Consumes(MediaType.APPLICATION_JSON)
Jian Li0c451802016-02-24 22:39:25 +0900220 public Response removeDevices(@PathParam("regionId") String regionId,
221 InputStream stream) {
222 final RegionId rid = RegionId.regionId(regionId);
223
224 try {
225 regionAdminService.removeDevices(rid, extractDeviceIds(stream));
226 } catch (IOException e) {
227 throw new IllegalArgumentException(e);
228 }
229
Jian Lic2a542b2016-05-10 11:48:19 -0700230 return Response.noContent().build();
Jian Li0c451802016-02-24 22:39:25 +0900231 }
232
233 /**
234 * Extracts device ids from a given JSON string.
235 *
236 * @param stream deviceIds JSON stream
237 * @return a set of device identifiers
238 * @throws IOException
239 */
240 private Set<DeviceId> extractDeviceIds(InputStream stream) throws IOException {
241 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
242 JsonNode deviceIdsJson = jsonTree.get("deviceIds");
243
244 if (deviceIdsJson == null || deviceIdsJson.size() == 0) {
245 throw new IllegalArgumentException(DEVICE_IDS_INVALID);
246 }
247
248 Set<DeviceId> deviceIds = Sets.newHashSet();
249 deviceIdsJson.forEach(did -> deviceIds.add(DeviceId.deviceId(did.asText())));
250
251 return deviceIds;
252 }
253}