/* * Copyright 2015-present 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 com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.Sets; 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.FloatingIp.Status; import org.onosproject.vtnrsc.FloatingIpId; import org.onosproject.vtnrsc.RouterId; import org.onosproject.vtnrsc.TenantId; import org.onosproject.vtnrsc.TenantNetworkId; import org.onosproject.vtnrsc.VirtualPortId; import org.onosproject.vtnrsc.floatingip.FloatingIpService; import org.onosproject.vtnweb.web.FloatingIpCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 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 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.CONFLICT; import static javax.ws.rs.core.Response.Status.CREATED; import static javax.ws.rs.core.Response.Status.NOT_FOUND; @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 DELETE_FAIL = "Floating IP is failed to delete!"; 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) @Consumes(MediaType.APPLICATION_JSON) public Response listFloatingIps() { Collection<FloatingIp> 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) @Consumes(MediaType.APPLICATION_JSON) public Response getFloatingIp(@PathParam("floatingIpUUID") String id, @QueryParam("fields") List<String> 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.isEmpty()) { 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<FloatingIp> 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<FloatingIp> 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(); } } @DELETE @Path("{floatingIpUUID}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response deleteSingleFloatingIp(@PathParam("floatingIpUUID") String id) throws IOException { try { FloatingIpId floatingIpId = FloatingIpId.of(id); Set<FloatingIpId> floatingIpIds = Sets.newHashSet(floatingIpId); Boolean result = nullIsNotFound(get(FloatingIpService.class) .removeFloatingIps(floatingIpIds), DELETE_FAIL); if (!result) { return Response.status(CONFLICT).entity(DELETE_FAIL).build(); } return Response.noContent().entity(DELETE_SUCCESS).build(); } catch (Exception e) { return Response.status(NOT_FOUND).entity(e.getMessage()).build(); } } private Collection<FloatingIp> createOrUpdateByInputStream(JsonNode subnode) throws Exception { checkNotNull(subnode, JSON_NOT_NULL); Collection<FloatingIp> 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 when any argument is illegal */ public Collection<FloatingIp> changeJsonToSub(JsonNode floatingIpNodes) throws Exception { checkNotNull(floatingIpNodes, JSON_NOT_NULL); Map<FloatingIpId, FloatingIp> subMap = new HashMap<FloatingIpId, FloatingIp>(); 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 <T> item type * @param message not found message * @return item if not null * @throws org.onlab.util.ItemNotFoundException if item is null */ protected <T> T nullIsNotFound(T item, String message) { if (item == null) { throw new ItemNotFoundException(message); } return item; } }