2 * Copyright 2015 Open Networking Laboratory
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
16 package org.onosproject.vtnweb.resources;
\r
18 import static com.google.common.base.Preconditions.checkArgument;
\r
19 import static com.google.common.base.Preconditions.checkNotNull;
\r
20 import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
\r
22 import java.io.IOException;
\r
23 import java.io.InputStream;
\r
24 import java.util.Collections;
\r
25 import java.util.HashMap;
\r
26 import java.util.HashSet;
\r
27 import java.util.Map;
\r
28 import java.util.Set;
\r
29 import java.util.concurrent.ConcurrentMap;
\r
31 import javax.ws.rs.Consumes;
\r
32 import javax.ws.rs.DELETE;
\r
33 import javax.ws.rs.GET;
\r
34 import javax.ws.rs.POST;
\r
35 import javax.ws.rs.PUT;
\r
36 import javax.ws.rs.Path;
\r
37 import javax.ws.rs.PathParam;
\r
38 import javax.ws.rs.Produces;
\r
39 import javax.ws.rs.core.MediaType;
\r
40 import javax.ws.rs.core.Response;
\r
42 import org.onlab.packet.IpAddress;
\r
43 import org.onlab.packet.IpAddress.Version;
\r
44 import org.onlab.packet.IpPrefix;
\r
45 import org.onlab.util.ItemNotFoundException;
\r
46 import org.onosproject.rest.AbstractWebResource;
\r
47 import org.onosproject.vtnrsc.AllocationPool;
\r
48 import org.onosproject.vtnrsc.DefaultAllocationPool;
\r
49 import org.onosproject.vtnrsc.DefaultHostRoute;
\r
50 import org.onosproject.vtnrsc.DefaultSubnet;
\r
51 import org.onosproject.vtnrsc.HostRoute;
\r
52 import org.onosproject.vtnrsc.Subnet;
\r
53 import org.onosproject.vtnrsc.SubnetId;
\r
54 import org.onosproject.vtnrsc.TenantId;
\r
55 import org.onosproject.vtnrsc.TenantNetworkId;
\r
56 import org.onosproject.vtnrsc.Subnet.Mode;
\r
57 import org.onosproject.vtnrsc.subnet.SubnetService;
\r
58 import org.onosproject.vtnrsc.web.SubnetCodec;
\r
59 import org.slf4j.Logger;
\r
60 import org.slf4j.LoggerFactory;
\r
62 import com.fasterxml.jackson.databind.JsonNode;
\r
63 import com.fasterxml.jackson.databind.ObjectMapper;
\r
64 import com.fasterxml.jackson.databind.node.ObjectNode;
\r
65 import com.google.common.collect.Maps;
\r
66 import com.google.common.collect.Sets;
\r
69 public class SubnetWebResource extends AbstractWebResource {
\r
70 private final Logger log = LoggerFactory.getLogger(SubnetWebResource.class);
\r
71 public static final String SUBNET_NOT_CREATE = "Subnets is failed to create!";
\r
72 public static final String SUBNET_NOT_FOUND = "Subnets is failed to update!";
\r
73 public static final String JSON_NOT_NULL = "JsonNode can not be null";
\r
76 @Produces(MediaType.APPLICATION_JSON)
\r
77 public Response listSubnets() {
\r
78 Iterable<Subnet> subnets = get(SubnetService.class).getSubnets();
\r
79 ObjectNode result = new ObjectMapper().createObjectNode();
\r
80 result.set("subnets", new SubnetCodec().encode(subnets, this));
\r
81 return ok(result.toString()).build();
\r
85 @Path("{subnetUUID}")
\r
86 @Produces(MediaType.APPLICATION_JSON)
\r
87 public Response getSubnet(@PathParam("subnetUUID") String id) {
\r
89 if (!get(SubnetService.class).exists(SubnetId.subnetId(id))) {
\r
90 return ok("The subnet does not exists").build();
\r
92 Subnet sub = nullIsNotFound(get(SubnetService.class)
\r
93 .getSubnet(SubnetId.subnetId(id)),
\r
96 ObjectNode result = new ObjectMapper().createObjectNode();
\r
97 result.set("subnet", new SubnetCodec().encode(sub, this));
\r
98 return ok(result.toString()).build();
\r
102 @Produces(MediaType.APPLICATION_JSON)
\r
103 @Consumes(MediaType.APPLICATION_JSON)
\r
104 public Response createSubnet(final InputStream input) {
\r
107 ObjectMapper mapper = new ObjectMapper();
\r
108 JsonNode subnode = mapper.readTree(input);
\r
109 Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
\r
110 Boolean result = nullIsNotFound((get(SubnetService.class)
\r
111 .createSubnets(subnets)),
\r
112 SUBNET_NOT_CREATE);
\r
115 return Response.status(204).entity(SUBNET_NOT_CREATE).build();
\r
117 return Response.status(202).entity(result.toString()).build();
\r
118 } catch (Exception e) {
\r
119 return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
\r
125 @Path("{subnetUUID}")
\r
126 @Produces(MediaType.APPLICATION_JSON)
\r
127 @Consumes(MediaType.APPLICATION_JSON)
\r
128 public Response updateSubnet(@PathParam("id") String id,
\r
129 final InputStream input) {
\r
131 ObjectMapper mapper = new ObjectMapper();
\r
132 JsonNode subnode = mapper.readTree(input);
\r
133 Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
\r
134 Boolean result = nullIsNotFound(get(SubnetService.class)
\r
135 .updateSubnets(subnets), SUBNET_NOT_FOUND);
\r
137 return Response.status(204).entity(SUBNET_NOT_FOUND).build();
\r
139 return Response.status(203).entity(result.toString()).build();
\r
140 } catch (Exception e) {
\r
141 return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
\r
146 @Path("{subnetUUID}")
\r
148 public Response deleteSingleSubnet(@PathParam("subnetUUID") String id)
\r
149 throws IOException {
\r
151 SubnetId subId = SubnetId.subnetId(id);
\r
152 Set<SubnetId> subIds = new HashSet<SubnetId>();
\r
154 get(SubnetService.class).removeSubnets(subIds);
\r
155 return Response.status(201).entity("SUCCESS").build();
\r
156 } catch (Exception e) {
\r
157 return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
\r
162 private Iterable<Subnet> createOrUpdateByInputStream(JsonNode subnode) {
\r
163 checkNotNull(subnode, JSON_NOT_NULL);
\r
164 Iterable<Subnet> subnets = null;
\r
165 JsonNode subnetNodes = subnode.get("subnets");
\r
166 if (subnetNodes == null) {
\r
167 subnetNodes = subnode.get("subnet");
\r
169 log.debug("subnetNodes is {}", subnetNodes.toString());
\r
170 if (subnetNodes.isArray()) {
\r
171 subnets = changeJsonToSubs(subnetNodes);
\r
173 subnets = changeJsonToSub(subnetNodes);
\r
179 * Returns a collection of subnets from subnetNodes.
\r
181 * @param subnetNodes the subnet json node
\r
182 * @return subnets a collection of subnets
\r
184 public Iterable<Subnet> changeJsonToSubs(JsonNode subnetNodes) {
\r
185 checkNotNull(subnetNodes, JSON_NOT_NULL);
\r
186 Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
\r
187 for (JsonNode subnetNode : subnetNodes) {
\r
188 if (!subnetNode.hasNonNull("id")) {
\r
191 SubnetId id = SubnetId.subnetId(subnetNode.get("id").asText());
\r
192 String subnetName = subnetNode.get("name").asText();
\r
193 TenantId tenantId = TenantId
\r
194 .tenantId(subnetNode.get("tenant_id").asText());
\r
195 TenantNetworkId networkId = TenantNetworkId
\r
196 .networkId(subnetNode.get("network_id").asText());
\r
197 Version ipVersion = Version
\r
198 .valueOf(subnetNode.get("ip_version").asText());
\r
199 IpPrefix cidr = IpPrefix.valueOf(subnetNode.get("cidr").asText());
\r
200 IpAddress gatewayIp = IpAddress
\r
201 .valueOf(subnetNode.get("gateway_ip").asText());
\r
202 Boolean dhcpEnabled = subnetNode.get("enable_dhcp").asBoolean();
\r
203 Boolean shared = subnetNode.get("shared").asBoolean();
\r
204 JsonNode hostRoutes = subnetNode.get("host_routes");
\r
205 Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
\r
206 JsonNode allocationPools = subnetNode.get("allocation_pools");
\r
207 Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);
\r
208 Mode ipV6AddressMode = Mode
\r
209 .valueOf(subnetNode.get("ipv6_address_mode").asText());
\r
210 Mode ipV6RaMode = Mode
\r
211 .valueOf(subnetNode.get("ipv6_ra_mode").asText());
\r
212 Subnet subnet = new DefaultSubnet(id, subnetName, networkId,
\r
213 tenantId, ipVersion, cidr,
\r
214 gatewayIp, dhcpEnabled, shared,
\r
215 Sets.newHashSet(hostRoutesIt), ipV6AddressMode,
\r
216 ipV6RaMode, Sets.newHashSet(allocationPoolsIt));
\r
217 subMap.put(id, subnet);
\r
219 return Collections.unmodifiableCollection(subMap.values());
\r
223 * Returns a collection of subnets from subnetNodes.
\r
225 * @param subnetNodes the subnet json node
\r
226 * @return subnets a collection of subnets
\r
228 public Iterable<Subnet> changeJsonToSub(JsonNode subnetNodes) {
\r
229 checkNotNull(subnetNodes, JSON_NOT_NULL);
\r
230 checkArgument(subnetNodes.get("enable_dhcp").isBoolean(), "enable_dhcp should be boolean");
\r
231 checkArgument(subnetNodes.get("shared").isBoolean(), "shared should be boolean");
\r
232 Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
\r
233 if (!subnetNodes.hasNonNull("id")) {
\r
236 SubnetId id = SubnetId.subnetId(subnetNodes.get("id").asText());
\r
237 String subnetName = subnetNodes.get("name").asText();
\r
238 TenantId tenantId = TenantId
\r
239 .tenantId(subnetNodes.get("tenant_id").asText());
\r
240 TenantNetworkId networkId = TenantNetworkId
\r
241 .networkId(subnetNodes.get("network_id").asText());
\r
242 String version = subnetNodes.get("ip_version").asText();
\r
246 ipVersion = Version.INET;
\r
249 ipVersion = Version.INET;
\r
252 throw new IllegalArgumentException("ipVersion should be 4 or 6.");
\r
255 IpPrefix cidr = IpPrefix.valueOf(subnetNodes.get("cidr").asText());
\r
256 IpAddress gatewayIp = IpAddress
\r
257 .valueOf(subnetNodes.get("gateway_ip").asText());
\r
258 Boolean dhcpEnabled = subnetNodes.get("enable_dhcp").asBoolean();
\r
259 Boolean shared = subnetNodes.get("shared").asBoolean();
\r
260 JsonNode hostRoutes = subnetNodes.get("host_routes");
\r
261 Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
\r
262 JsonNode allocationPools = subnetNodes.get("allocation_pools");
\r
263 Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);
\r
265 Mode ipV6AddressMode = getMode(subnetNodes.get("ipv6_address_mode")
\r
267 Mode ipV6RaMode = getMode(subnetNodes.get("ipv6_ra_mode").asText());
\r
269 Subnet subnet = new DefaultSubnet(id, subnetName, networkId, tenantId,
\r
270 ipVersion, cidr, gatewayIp,
\r
271 dhcpEnabled, shared, Sets.newHashSet(hostRoutesIt),
\r
272 ipV6AddressMode, ipV6RaMode,
\r
273 Sets.newHashSet(allocationPoolsIt));
\r
274 subMap.put(id, subnet);
\r
275 return Collections.unmodifiableCollection(subMap.values());
\r
279 * Gets ipv6_address_mode or ipv6_ra_mode type.
\r
281 * @param mode the String value in JsonNode
\r
282 * @return ipV6Mode Mode of the ipV6Mode
\r
284 private Mode getMode(String mode) {
\r
286 if (mode == null) {
\r
290 case "dhcpv6-stateful":
\r
291 ipV6Mode = Mode.DHCPV6_STATEFUL;
\r
293 case "dhcpv6-stateless":
\r
294 ipV6Mode = Mode.DHCPV6_STATELESS;
\r
297 ipV6Mode = Mode.SLAAC;
\r
306 * Changes JsonNode alocPools to a collection of the alocPools.
\r
308 * @param allocationPools the allocationPools JsonNode
\r
309 * @return a collection of allocationPools
\r
311 public Iterable<AllocationPool> jsonNodeToAllocationPools(JsonNode allocationPools) {
\r
312 checkNotNull(allocationPools, JSON_NOT_NULL);
\r
313 ConcurrentMap<Integer, AllocationPool> alocplMaps = Maps
\r
314 .newConcurrentMap();
\r
316 for (JsonNode node : allocationPools) {
\r
317 IpAddress startIp = IpAddress.valueOf(node.get("start").asText());
\r
318 IpAddress endIp = IpAddress.valueOf(node.get("end").asText());
\r
319 AllocationPool alocPls = new DefaultAllocationPool(startIp, endIp);
\r
320 alocplMaps.putIfAbsent(i, alocPls);
\r
323 return Collections.unmodifiableCollection(alocplMaps.values());
\r
327 * Changes hostRoutes JsonNode to a collection of the hostRoutes.
\r
329 * @param hostRoutes the hostRoutes json node
\r
330 * @return a collection of hostRoutes
\r
332 public Iterable<HostRoute> jsonNodeToHostRoutes(JsonNode hostRoutes) {
\r
333 checkNotNull(hostRoutes, JSON_NOT_NULL);
\r
334 ConcurrentMap<Integer, HostRoute> hostRouteMaps = Maps
\r
335 .newConcurrentMap();
\r
337 for (JsonNode node : hostRoutes) {
\r
338 IpAddress nexthop = IpAddress.valueOf(node.get("nexthop").asText());
\r
339 IpPrefix destination = IpPrefix.valueOf(node.get("destination")
\r
341 HostRoute hostRoute = new DefaultHostRoute(nexthop, destination);
\r
342 hostRouteMaps.putIfAbsent(i, hostRoute);
\r
345 return Collections.unmodifiableCollection(hostRouteMaps.values());
\r
349 * Returns the specified item if that items is null; otherwise throws not
\r
352 * @param item item to check
\r
353 * @param <T> item type
\r
354 * @param message not found message
\r
355 * @return item if not null
\r
356 * @throws org.onlab.util.ItemNotFoundException if item is null
\r
358 protected <T> T nullIsNotFound(T item, String message) {
\r
359 if (item == null) {
\r
360 throw new ItemNotFoundException(message);
\r