blob: 779777f944b37442d23bd59e0d92de69b9adeea8 [file] [log] [blame]
CNlucius5b2fff12015-08-20 14:13:46 +08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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.vtnweb.resources;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
20
21import java.io.IOException;
22import java.io.InputStream;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Map;
27import java.util.Set;
28import java.util.concurrent.ConcurrentMap;
29
30import javax.ws.rs.Consumes;
31import javax.ws.rs.DELETE;
32import javax.ws.rs.GET;
33import javax.ws.rs.POST;
34import javax.ws.rs.PUT;
35import javax.ws.rs.Path;
36import javax.ws.rs.PathParam;
37import javax.ws.rs.Produces;
38import javax.ws.rs.core.MediaType;
39import javax.ws.rs.core.Response;
40
41import org.onlab.packet.IpAddress;
42import org.onlab.packet.IpAddress.Version;
43import org.onlab.packet.IpPrefix;
44import org.onlab.util.ItemNotFoundException;
45import org.onosproject.rest.AbstractWebResource;
46import org.onosproject.vtnrsc.AllocationPool;
47import org.onosproject.vtnrsc.DefaultAllocationPool;
48import org.onosproject.vtnrsc.DefaultHostRoute;
49import org.onosproject.vtnrsc.DefaultSubnet;
50import org.onosproject.vtnrsc.HostRoute;
51import org.onosproject.vtnrsc.Subnet;
52import org.onosproject.vtnrsc.SubnetId;
53import org.onosproject.vtnrsc.TenantId;
54import org.onosproject.vtnrsc.TenantNetworkId;
55import org.onosproject.vtnrsc.Subnet.Mode;
56import org.onosproject.vtnrsc.subnet.SubnetService;
57import org.onosproject.vtnrsc.web.SubnetCodec;
58import org.slf4j.Logger;
59import org.slf4j.LoggerFactory;
60
61import com.fasterxml.jackson.databind.JsonNode;
62import com.fasterxml.jackson.databind.ObjectMapper;
63import com.fasterxml.jackson.databind.node.ObjectNode;
64import com.google.common.collect.Maps;
65
66@Path("subnets")
67public class SubnetWebResource extends AbstractWebResource {
68 private final Logger log = LoggerFactory.getLogger(SubnetWebResource.class);
69 public static final String SUBNET_NOT_CREATE = "Subnets is failed to create!";
70 public static final String SUBNET_NOT_FOUND = "Subnets is failed to update!";
71 public static final String JSON_NOT_NULL = "JsonNode can not be null";
72
73 @GET
74 @Produces(MediaType.APPLICATION_JSON)
75 public Response listSubnets() {
76 Iterable<Subnet> subnets = get(SubnetService.class).getSubnets();
77 ObjectNode result = new ObjectMapper().createObjectNode();
78 result.set("subnets", new SubnetCodec().encode(subnets, this));
79 return ok(result.toString()).build();
80 }
81
82 @GET
83 @Path("{subnetUUID}")
84 @Produces(MediaType.APPLICATION_JSON)
85 public Response getSubnet(@PathParam("subnetUUID") String id) {
86
87 if (!get(SubnetService.class).exists(SubnetId.subnetId(id))) {
88 return ok("The subnet does not exists").build();
89 }
90 Subnet sub = nullIsNotFound(get(SubnetService.class)
91 .getSubnet(SubnetId.subnetId(id)),
92 SUBNET_NOT_FOUND);
93
94 ObjectNode result = new ObjectMapper().createObjectNode();
95 result.set("subnet", new SubnetCodec().encode(sub, this));
96 return ok(result.toString()).build();
97 }
98
99 @POST
100 @Produces(MediaType.APPLICATION_JSON)
101 @Consumes(MediaType.APPLICATION_JSON)
102 public Response createSubnet(final InputStream input) {
103
104 try {
105 ObjectMapper mapper = new ObjectMapper();
106 JsonNode subnode = mapper.readTree(input);
107 Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
108 Boolean result = nullIsNotFound((get(SubnetService.class)
109 .createSubnets(subnets)),
110 SUBNET_NOT_CREATE);
111
112 if (!result) {
113 return Response.status(204).entity(SUBNET_NOT_CREATE).build();
114 }
115 return Response.status(202).entity(result.toString()).build();
116 } catch (Exception e) {
117 return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
118 .build();
119 }
120 }
121
122 @PUT
123 @Path("{subnetUUID}")
124 @Produces(MediaType.APPLICATION_JSON)
125 @Consumes(MediaType.APPLICATION_JSON)
126 public Response updateSubnet(@PathParam("id") String id,
127 final InputStream input) {
128 try {
129 ObjectMapper mapper = new ObjectMapper();
130 JsonNode subnode = mapper.readTree(input);
131 Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
132 Boolean result = nullIsNotFound(get(SubnetService.class)
133 .updateSubnets(subnets), SUBNET_NOT_FOUND);
134 if (!result) {
135 return Response.status(204).entity(SUBNET_NOT_FOUND).build();
136 }
137 return Response.status(203).entity(result.toString()).build();
138 } catch (Exception e) {
139 return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
140 .build();
141 }
142 }
143
144 @Path("{subnetUUID}")
145 @DELETE
146 public Response deleteSingleSubnet(@PathParam("subnetUUID") String id)
147 throws IOException {
148 try {
149 SubnetId subId = SubnetId.subnetId(id);
150 Set<SubnetId> subIds = new HashSet<SubnetId>();
151 subIds.add(subId);
152 get(SubnetService.class).removeSubnets(subIds);
153 return Response.status(201).entity("SUCCESS").build();
154 } catch (Exception e) {
155 return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
156 .build();
157 }
158 }
159
160 private Iterable<Subnet> createOrUpdateByInputStream(JsonNode subnode) {
161 checkNotNull(subnode, JSON_NOT_NULL);
162 Iterable<Subnet> subnets = null;
163 JsonNode subnetNodes = subnode.get("subnets");
164 if (subnetNodes == null) {
165 subnetNodes = subnode.get("subnet");
166 }
167 log.debug("subnetNodes is {}", subnetNodes.toString());
168 if (subnetNodes.isArray()) {
169 subnets = changeJsonToSubs(subnetNodes);
170 } else {
171 subnets = changeJsonToSub(subnetNodes);
172 }
173 return subnets;
174 }
175
176 /**
177 * Returns a collection of subnets from subnetNodes.
178 *
179 * @param subnetNodes the subnet json node
180 * @return subnets a collection of subnets
181 */
182 public Iterable<Subnet> changeJsonToSubs(JsonNode subnetNodes) {
183 checkNotNull(subnetNodes, JSON_NOT_NULL);
184 Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
185 for (JsonNode subnetNode : subnetNodes) {
186 if (!subnetNode.hasNonNull("id")) {
187 return null;
188 }
189 SubnetId id = SubnetId.subnetId(subnetNode.get("id").asText());
190 String subnetName = subnetNode.get("name").asText();
191 TenantId tenantId = TenantId
192 .tenantId(subnetNode.get("tenant_id").asText());
193 TenantNetworkId networkId = TenantNetworkId
194 .networkId(subnetNode.get("network_id").asText());
195 Version ipVersion = Version
196 .valueOf(subnetNode.get("ip_version").asText());
197 IpPrefix cidr = IpPrefix.valueOf(subnetNode.get("cidr").asText());
198 IpAddress gatewayIp = IpAddress
199 .valueOf(subnetNode.get("gateway_ip").asText());
200 Boolean dhcpEnabled = subnetNode.get("enable_dhcp").asBoolean();
201 Boolean shared = subnetNode.get("shared").asBoolean();
202 JsonNode hostRoutes = subnetNode.get("host_routes");
203 Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
204 JsonNode allocationPools = subnetNode.get("allocation_pools");
205 Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);
206 Mode ipV6AddressMode = Mode
207 .valueOf(subnetNode.get("ipv6_address_mode").asText());
208 Mode ipV6RaMode = Mode
209 .valueOf(subnetNode.get("ipv6_ra_mode").asText());
210 Subnet subnet = new DefaultSubnet(id, subnetName, networkId,
211 tenantId, ipVersion, cidr,
212 gatewayIp, dhcpEnabled, shared,
213 hostRoutesIt, ipV6AddressMode,
214 ipV6RaMode, allocationPoolsIt);
215 subMap.put(id, subnet);
216 }
217 return Collections.unmodifiableCollection(subMap.values());
218 }
219
220 /**
221 * Returns a collection of subnets from subnetNodes.
222 *
223 * @param subnetNodes the subnet json node
224 * @return subnets a collection of subnets
225 */
226 public Iterable<Subnet> changeJsonToSub(JsonNode subnetNodes) {
227 checkNotNull(subnetNodes, JSON_NOT_NULL);
228 Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
229 if (!subnetNodes.hasNonNull("id")) {
230 return null;
231 }
232 SubnetId id = SubnetId.subnetId(subnetNodes.get("id").asText());
233 String subnetName = subnetNodes.get("name").asText();
234 TenantId tenantId = TenantId
235 .tenantId(subnetNodes.get("tenant_id").asText());
236 TenantNetworkId networkId = TenantNetworkId
237 .networkId(subnetNodes.get("network_id").asText());
238 String version = subnetNodes.get("ip_version").asText();
239 Version ipVersion;
240 switch (version) {
241 case "4":
242 ipVersion = Version.INET;
243 break;
244 case "6":
245 ipVersion = Version.INET;
246 break;
247 default:
248 ipVersion = null;
249 }
250
251 IpPrefix cidr = IpPrefix.valueOf(subnetNodes.get("cidr").asText());
252 IpAddress gatewayIp = IpAddress
253 .valueOf(subnetNodes.get("gateway_ip").asText());
254 Boolean dhcpEnabled = subnetNodes.get("enable_dhcp").asBoolean();
255 Boolean shared = subnetNodes.get("shared").asBoolean();
256 JsonNode hostRoutes = subnetNodes.get("host_routes");
257 Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
258 JsonNode allocationPools = subnetNodes.get("allocation_pools");
259 Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);
260
261 Mode ipV6AddressMode = getMode(subnetNodes.get("ipv6_address_mode")
262 .asText());
263 Mode ipV6RaMode = getMode(subnetNodes.get("ipv6_ra_mode").asText());
264
265 Subnet subnet = new DefaultSubnet(id, subnetName, networkId, tenantId,
266 ipVersion, cidr, gatewayIp,
267 dhcpEnabled, shared, hostRoutesIt,
268 ipV6AddressMode, ipV6RaMode,
269 allocationPoolsIt);
270 subMap.put(id, subnet);
271 return Collections.unmodifiableCollection(subMap.values());
272 }
273
274 /**
275 * Gets ipv6_address_mode or ipv6_ra_mode type.
276 *
277 * @param mode the String value in JsonNode
278 * @return ipV6Mode Mode of the ipV6Mode
279 */
280 private Mode getMode(String mode) {
281 Mode ipV6Mode;
282 if (mode == null) {
283 return null;
284 }
285 switch (mode) {
286 case "dhcpv6-stateful":
287 ipV6Mode = Mode.DHCPV6_STATEFUL;
288 break;
289 case "dhcpv6-stateless":
290 ipV6Mode = Mode.DHCPV6_STATELESS;
291 break;
292 case "slaac":
293 ipV6Mode = Mode.SLAAC;
294 break;
295 default:
296 ipV6Mode = null;
297 }
298 return ipV6Mode;
299 }
300
301 /**
302 * Changes JsonNode alocPools to a collection of the alocPools.
303 *
304 * @param allocationPools the allocationPools JsonNode
305 * @return a collection of allocationPools
306 */
307 public Iterable<AllocationPool> jsonNodeToAllocationPools(JsonNode allocationPools) {
308 checkNotNull(allocationPools, JSON_NOT_NULL);
309 ConcurrentMap<Integer, AllocationPool> alocplMaps = Maps
310 .newConcurrentMap();
311 Integer i = 0;
312 for (JsonNode node : allocationPools) {
313 IpAddress startIp = IpAddress.valueOf(node.get("start").asText());
314 IpAddress endIp = IpAddress.valueOf(node.get("end").asText());
315 AllocationPool alocPls = new DefaultAllocationPool(startIp, endIp);
316 alocplMaps.putIfAbsent(i, alocPls);
317 i++;
318 }
319 return Collections.unmodifiableCollection(alocplMaps.values());
320 }
321
322 /**
323 * Changes hostRoutes JsonNode to a collection of the hostRoutes.
324 *
325 * @param hostRoutes the hostRoutes json node
326 * @return a collection of hostRoutes
327 */
328 public Iterable<HostRoute> jsonNodeToHostRoutes(JsonNode hostRoutes) {
329 checkNotNull(hostRoutes, JSON_NOT_NULL);
330 ConcurrentMap<Integer, HostRoute> hostRouteMaps = Maps
331 .newConcurrentMap();
332 Integer i = 0;
333 for (JsonNode node : hostRoutes) {
334 IpAddress nexthop = IpAddress.valueOf(node.get("nexthop").asText());
335 IpPrefix destination = IpPrefix.valueOf(node.get("destination")
336 .asText());
337 HostRoute hostRoute = new DefaultHostRoute(nexthop, destination);
338 hostRouteMaps.putIfAbsent(i, hostRoute);
339 i++;
340 }
341 return Collections.unmodifiableCollection(hostRouteMaps.values());
342 }
343
344 /**
345 * Returns the specified item if that items is null; otherwise throws not
346 * found exception.
347 *
348 * @param item item to check
349 * @param <T> item type
350 * @param message not found message
351 * @return item if not null
352 * @throws org.onlab.util.ItemNotFoundException if item is null
353 */
354 protected <T> T nullIsNotFound(T item, String message) {
355 if (item == null) {
356 throw new ItemNotFoundException(message);
357 }
358 return item;
359 }
360
361}