From 9d54c26ea9ed3a3bffadb87e26e082e28eaae188 Mon Sep 17 00:00:00 2001 From: jiangrui Date: Sat, 28 Nov 2015 14:23:39 +0800 Subject: [PATCH] [ONOS-2755] add restfull service of floatingIp Change-Id: Ife1ee53639f64136d72267d205c71d2766d7d97b --- .../resources/FloatingIpWebResource.java | 285 ++++++++++++++++++ .../vtnweb/web/FloatingIpCodec.java | 98 ++++++ .../vtnweb/src/main/webapp/WEB-INF/web.xml | 2 + 3 files changed, 385 insertions(+) create mode 100644 apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java create mode 100644 apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java new file mode 100644 index 0000000000..9fdcb5298b --- /dev/null +++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java @@ -0,0 +1,285 @@ +/* + * 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.vtnweb.resources; + +import static com.google.common.base.Preconditions.checkNotNull; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.CREATED; +import static javax.ws.rs.core.Response.Status.CONFLICT; +import static javax.ws.rs.core.Response.Status.NO_CONTENT; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onlab.packet.IpAddress; +import org.onlab.util.ItemNotFoundException; +import org.onosproject.rest.AbstractWebResource; +import org.onosproject.vtnrsc.DefaultFloatingIp; +import org.onosproject.vtnrsc.FloatingIp; +import org.onosproject.vtnrsc.FloatingIpId; +import org.onosproject.vtnrsc.TenantId; +import org.onosproject.vtnrsc.TenantNetworkId; +import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.RouterId; +import org.onosproject.vtnrsc.FloatingIp.Status; +import org.onosproject.vtnrsc.floatingip.FloatingIpService; +import org.onosproject.vtnweb.web.FloatingIpCodec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.Sets; + +@Path("floatingips") +public class FloatingIpWebResource extends AbstractWebResource { + private final Logger log = LoggerFactory + .getLogger(FloatingIpWebResource.class); + public static final String CREATE_FAIL = "Floating IP is failed to create!"; + public static final String UPDATE_FAIL = "Floating IP is failed to update!"; + public static final String GET_FAIL = "Floating IP is failed to get!"; + public static final String NOT_EXIST = "Floating IP does not exist!"; + public static final String DELETE_SUCCESS = "Floating IP delete success!"; + public static final String JSON_NOT_NULL = "JsonNode can not be null"; + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response listFloatingIps() { + Collection floatingIps = get(FloatingIpService.class) + .getFloatingIps(); + ObjectNode result = new ObjectMapper().createObjectNode(); + result.set("floatingips", + new FloatingIpCodec().encode(floatingIps, this)); + return ok(result.toString()).build(); + } + + @GET + @Path("{floatingIpUUID}") + @Produces(MediaType.APPLICATION_JSON) + public Response getFloatingIp(@PathParam("floatingIpUUID") String id, + @QueryParam("fields") List fields) { + + if (!get(FloatingIpService.class).exists(FloatingIpId.of(id))) { + return Response.status(NOT_FOUND).entity(NOT_EXIST).build(); + } + FloatingIp sub = nullIsNotFound(get(FloatingIpService.class) + .getFloatingIp(FloatingIpId.of(id)), GET_FAIL); + + ObjectNode result = new ObjectMapper().createObjectNode(); + if (fields.size() > 0) { + result.set("floatingip", + new FloatingIpCodec().extracFields(sub, this, fields)); + } else { + result.set("floatingip", new FloatingIpCodec().encode(sub, this)); + } + return ok(result.toString()).build(); + } + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response createFloatingIp(final InputStream input) { + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode subnode = mapper.readTree(input); + Collection floatingIps = createOrUpdateByInputStream(subnode); + Boolean result = nullIsNotFound((get(FloatingIpService.class) + .createFloatingIps(floatingIps)), + CREATE_FAIL); + if (!result) { + return Response.status(CONFLICT).entity(CREATE_FAIL).build(); + } + return Response.status(CREATED).entity(result.toString()).build(); + + } catch (Exception e) { + return Response.status(BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + @PUT + @Path("{floatingIpUUID}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response updateFloatingIp(@PathParam("floatingIpUUID") String id, + final InputStream input) { + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode subnode = mapper.readTree(input); + Collection floatingIps = createOrUpdateByInputStream(subnode); + Boolean result = nullIsNotFound(get(FloatingIpService.class) + .updateFloatingIps(floatingIps), UPDATE_FAIL); + if (!result) { + return Response.status(CONFLICT).entity(UPDATE_FAIL).build(); + } + return ok(result.toString()).build(); + } catch (Exception e) { + return Response.status(BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + @Path("{floatingIpUUID}") + @DELETE + public Response deleteSingleFloatingIp(@PathParam("floatingIpUUID") String id) + throws IOException { + try { + FloatingIpId floatingIpId = FloatingIpId.of(id); + Set floatingIpIds = Sets.newHashSet(floatingIpId); + get(FloatingIpService.class).removeFloatingIps(floatingIpIds); + return Response.status(NO_CONTENT).entity(DELETE_SUCCESS).build(); + } catch (Exception e) { + return Response.status(NOT_FOUND).entity(e.getMessage()).build(); + } + } + + private Collection createOrUpdateByInputStream(JsonNode subnode) + throws Exception { + checkNotNull(subnode, JSON_NOT_NULL); + Collection floatingIps = null; + JsonNode floatingIpNodes = subnode.get("floatingips"); + if (floatingIpNodes == null) { + floatingIpNodes = subnode.get("floatingip"); + } + log.debug("floatingNodes is {}", floatingIpNodes.toString()); + + if (floatingIpNodes.isArray()) { + throw new IllegalArgumentException("only singleton requests allowed"); + } else { + floatingIps = changeJsonToSub(floatingIpNodes); + } + return floatingIps; + } + + /** + * Returns a collection of floatingIps from floatingIpNodes. + * + * @param floatingIpNodes the floatingIp json node + * @return floatingIps a collection of floatingIp + * @throws Exception + */ + public Collection changeJsonToSub(JsonNode floatingIpNodes) + throws Exception { + checkNotNull(floatingIpNodes, JSON_NOT_NULL); + Map subMap = new HashMap(); + if (!floatingIpNodes.hasNonNull("id")) { + throw new IllegalArgumentException("id should not be null"); + } else if (floatingIpNodes.get("id").asText().isEmpty()) { + throw new IllegalArgumentException("id should not be empty"); + } + FloatingIpId id = FloatingIpId.of(floatingIpNodes.get("id") + .asText()); + + if (!floatingIpNodes.hasNonNull("tenant_id")) { + throw new IllegalArgumentException("tenant_id should not be null"); + } else if (floatingIpNodes.get("tenant_id").asText().isEmpty()) { + throw new IllegalArgumentException("tenant_id should not be empty"); + } + TenantId tenantId = TenantId.tenantId(floatingIpNodes.get("tenant_id") + .asText()); + + if (!floatingIpNodes.hasNonNull("floating_network_id")) { + throw new IllegalArgumentException( + "floating_network_id should not be null"); + } else if (floatingIpNodes.get("floating_network_id").asText() + .isEmpty()) { + throw new IllegalArgumentException( + "floating_network_id should not be empty"); + } + TenantNetworkId networkId = TenantNetworkId.networkId(floatingIpNodes + .get("floating_network_id").asText()); + + VirtualPortId portId = null; + if (floatingIpNodes.hasNonNull("port_id")) { + portId = VirtualPortId.portId(floatingIpNodes.get("port_id") + .asText()); + } + + RouterId routerId = null; + if (floatingIpNodes.hasNonNull("router_id")) { + routerId = RouterId.valueOf(floatingIpNodes.get("router_id") + .asText()); + } + + IpAddress fixedIp = null; + if (floatingIpNodes.hasNonNull("fixed_ip_address")) { + fixedIp = IpAddress.valueOf(floatingIpNodes.get("fixed_ip_address") + .asText()); + } + + if (!floatingIpNodes.hasNonNull("floating_ip_address")) { + throw new IllegalArgumentException( + "floating_ip_address should not be null"); + } else if (floatingIpNodes.get("floating_ip_address").asText() + .isEmpty()) { + throw new IllegalArgumentException( + "floating_ip_address should not be empty"); + } + IpAddress floatingIp = IpAddress.valueOf(floatingIpNodes + .get("floating_ip_address").asText()); + + if (!floatingIpNodes.hasNonNull("status")) { + throw new IllegalArgumentException("status should not be null"); + } else if (floatingIpNodes.get("status").asText().isEmpty()) { + throw new IllegalArgumentException("status should not be empty"); + } + Status status = Status.valueOf(floatingIpNodes.get("status").asText()); + + DefaultFloatingIp floatingIpObj = new DefaultFloatingIp(id, tenantId, + networkId, + portId, + routerId, + floatingIp, + fixedIp, status); + subMap.put(id, floatingIpObj); + return Collections.unmodifiableCollection(subMap.values()); + } + + /** + * Returns the specified item if that items is null; otherwise throws not + * found exception. + * + * @param item item to check + * @param item type + * @param message not found message + * @return item if not null + * @throws org.onlab.util.ItemNotFoundException if item is null + */ + protected T nullIsNotFound(T item, String message) { + if (item == null) { + throw new ItemNotFoundException(message); + } + return item; + } +} diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java new file mode 100644 index 0000000000..ff5aebb409 --- /dev/null +++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java @@ -0,0 +1,98 @@ +/* + * 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.vtnweb.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Iterator; +import java.util.List; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.vtnrsc.FloatingIp; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * FloatingIp JSON codec. + */ +public final class FloatingIpCodec extends JsonCodec { + @Override + public ObjectNode encode(FloatingIp floatingIp, CodecContext context) { + checkNotNull(floatingIp, "floatingIp cannot be null"); + ObjectNode result = context + .mapper() + .createObjectNode() + .put("id", floatingIp.id().floatingIpId().toString()) + .put("floating_network_id", floatingIp.networkId().toString()) + .put("router_id", + floatingIp.routerId() == null ? null : floatingIp + .routerId().routerId()) + .put("tenant_id", floatingIp.tenantId().toString()) + .put("port_id", + floatingIp.portId() == null ? null : floatingIp.portId() + .toString()) + .put("fixed_ip_address", + floatingIp.fixedIp() == null ? null : floatingIp.fixedIp() + .toString()) + .put("floating_ip_address", floatingIp.floatingIp().toString()) + .put("status", floatingIp.status().toString()); + return result; + } + + public ObjectNode extracFields(FloatingIp floatingIp, CodecContext context, + List fields) { + checkNotNull(floatingIp, "floatingIp cannot be null"); + ObjectNode result = context.mapper().createObjectNode(); + Iterator i = fields.iterator(); + while (i.hasNext()) { + String s = i.next(); + if (s.equals("floating_network_id")) { + result.put("floating_network_id", floatingIp.networkId() + .toString()); + } + if (s.equals("router_id")) { + result.put("router_id", + floatingIp.routerId() == null ? null : floatingIp + .routerId().routerId()); + } + if (s.equals("tenant_id")) { + result.put("tenant_id", floatingIp.tenantId().toString()); + } + if (s.equals("port_id")) { + result.put("port_id", + floatingIp.portId() == null ? null : floatingIp + .portId().toString()); + } + if (s.equals("id")) { + result.put("id", floatingIp.id().floatingIpId().toString()); + } + if (s.equals("fixed_ip_address")) { + result.put("fixed_ip_address", + floatingIp.fixedIp() == null ? null : floatingIp + .fixedIp().toString()); + } + if (s.equals("floating_ip_address")) { + result.put("floating_ip_address", floatingIp.floatingIp() + .toString()); + } + if (s.equals("status")) { + result.put("status", floatingIp.status().toString()); + } + } + return result; + } +} diff --git a/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml b/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml index 97337960ad..13b377bf91 100644 --- a/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml +++ b/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml @@ -37,6 +37,8 @@ org.onosproject.vtnweb.resources.PortChainWebResource org.onosproject.vtnweb.resources.PortPairGroupWebResource org.onosproject.vtnweb.resources.PortPairWebResource + org.onosproject.vtnweb.resources.FloatingIpWebResource + org.onosproject.vtnweb.resources.RouterWebResource 1