/* * 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.Maps; import org.onlab.util.ItemNotFoundException; import org.onosproject.rest.AbstractWebResource; import org.onosproject.vtnrsc.DefaultTenantNetwork; import org.onosproject.vtnrsc.PhysicalNetwork; import org.onosproject.vtnrsc.SegmentationId; import org.onosproject.vtnrsc.TenantId; import org.onosproject.vtnrsc.TenantNetwork; import org.onosproject.vtnrsc.TenantNetwork.State; import org.onosproject.vtnrsc.TenantNetwork.Type; import org.onosproject.vtnrsc.TenantNetworkId; import org.onosproject.vtnrsc.service.VtnRscService; import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService; import org.onosproject.vtnweb.web.TenantNetworkCodec; 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.InputStream; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ConcurrentMap; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; /** * REST resource for interacting with the inventory of networks. */ @Path("networks") public class TenantNetworkWebResource extends AbstractWebResource { public static final String NETWORK_NOT_FOUND = "Network is not found"; public static final String NETWORK_ID_EXIST = "Network id is existed"; public static final String NETWORK_ID_NOT_EXIST = "Network id is not existed"; public static final String CREATE_NETWORK = "create network"; public static final String UPDATE_NETWORK = "update network"; public static final String DELETE_NETWORK = "delete network"; public static final String JSON_NOT_NULL = "JsonNode can not be null"; protected static final Logger log = LoggerFactory .getLogger(TenantNetworkWebResource.class); private final ConcurrentMap<TenantNetworkId, TenantNetwork> networksMap = Maps .newConcurrentMap(); @GET @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Response getNetworks(@QueryParam("id") String queryId, @QueryParam("name") String queryName, @QueryParam("admin_state_up") String queryadminStateUp, @QueryParam("status") String querystate, @QueryParam("shared") String queryshared, @QueryParam("tenant_id") String querytenantId, @QueryParam("router:external") String routerExternal, @QueryParam("provider:network_type") String type, @QueryParam("provider:physical_network") String physicalNetwork, @QueryParam("provider:segmentation_id") String segmentationId) { Iterable<TenantNetwork> networks = get(TenantNetworkService.class) .getNetworks(); Iterator<TenantNetwork> networkors = networks.iterator(); while (networkors.hasNext()) { TenantNetwork network = networkors.next(); if ((queryId == null || queryId.equals(network.id().toString())) && (queryName == null || queryName.equals(network.name())) && (queryadminStateUp == null || queryadminStateUp .equals(Boolean.toString(network.adminStateUp()))) && (querystate == null || querystate.equals(network.state() .toString())) && (queryshared == null || queryshared.equals(Boolean.toString(network .shared()))) && (querytenantId == null || querytenantId.equals(network .tenantId().toString())) && (routerExternal == null || routerExternal.equals(Boolean.toString(network .routerExternal()))) && (type == null || type.equals(network.type().toString())) && (physicalNetwork == null || physicalNetwork .equals(network.physicalNetwork().toString())) && (segmentationId == null || segmentationId.equals(network .segmentationId().toString()))) { networksMap.putIfAbsent(network.id(), network); } } networks = Collections.unmodifiableCollection(networksMap.values()); ObjectNode result = new ObjectMapper().createObjectNode(); result.set("networks", new TenantNetworkCodec().encode(networks, this)); return ok(result.toString()).build(); } private State isState(String state) { if ("ACTIVE".equals(state)) { return TenantNetwork.State.ACTIVE; } else if ("BUILD".equals(state)) { return TenantNetwork.State.BUILD; } else if ("DOWN".equals(state)) { return TenantNetwork.State.DOWN; } else if ("ERROR".equals(state)) { return TenantNetwork.State.ERROR; } else { return null; } } private Type isType(String type) { if ("LOCAL".equals(type)) { return TenantNetwork.Type.LOCAL; } else { return null; } } @GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Response getNetwork(@PathParam("id") String id) { if (!get(TenantNetworkService.class).exists(TenantNetworkId .networkId(id))) { return Response.status(NOT_FOUND) .entity(NETWORK_NOT_FOUND).build(); } TenantNetwork network = nullIsNotFound(get(TenantNetworkService.class) .getNetwork(TenantNetworkId.networkId(id)), NETWORK_NOT_FOUND); ObjectNode result = new ObjectMapper().createObjectNode(); result.set("network", new TenantNetworkCodec().encode(network, this)); return ok(result.toString()).build(); } @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Response createNetworks(InputStream input) { try { ObjectMapper mapper = new ObjectMapper(); JsonNode cfg = mapper.readTree(input); JsonNode nodes = null; Iterable<TenantNetwork> networks = null; if (cfg.get("network") != null) { nodes = cfg.get("network"); if (nodes.isArray()) { networks = changeJson2objs(nodes); } else { networks = changeJson2obj(CREATE_NETWORK, null, nodes); } } else if (cfg.get("networks") != null) { nodes = cfg.get("networks"); networks = changeJson2objs(nodes); } Boolean issuccess = nullIsNotFound((get(TenantNetworkService.class) .createNetworks(networks)), NETWORK_NOT_FOUND); if (!issuccess) { return Response.status(INTERNAL_SERVER_ERROR) .entity(NETWORK_ID_EXIST).build(); } return Response.status(OK).entity(issuccess.toString()).build(); } catch (Exception e) { log.error("Creates tenantNetwork exception {}.", e.toString()); return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString()) .build(); } } @PUT @Path("{id}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Response updateNetworks(@PathParam("id") String id, InputStream input) { try { ObjectMapper mapper = new ObjectMapper(); JsonNode cfg = mapper.readTree(input); JsonNode nodes = null; Iterable<TenantNetwork> networks = null; if (cfg.get("network") != null) { nodes = cfg.get("network"); if (nodes.isArray()) { networks = changeJson2objs(nodes); } else { networks = changeJson2obj(UPDATE_NETWORK, TenantNetworkId.networkId(id), nodes); } } else if (cfg.get("networks") != null) { nodes = cfg.get("networks"); networks = changeJson2objs(nodes); } Boolean issuccess = nullIsNotFound((get(TenantNetworkService.class) .updateNetworks(networks)), NETWORK_NOT_FOUND); if (!issuccess) { return Response.status(INTERNAL_SERVER_ERROR) .entity(NETWORK_ID_NOT_EXIST).build(); } return Response.status(OK).entity(issuccess.toString()).build(); } catch (Exception e) { log.error("Updates tenantNetwork failed because of exception {}.", e.toString()); return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString()) .build(); } } @DELETE @Path("{id}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response deleteNetworks(@PathParam("id") String id) { log.debug("Deletes network by identifier {}.", id); Set<TenantNetworkId> networkSet = new HashSet<>(); networkSet.add(TenantNetworkId.networkId(id)); Boolean issuccess = nullIsNotFound(get(TenantNetworkService.class) .removeNetworks(networkSet), NETWORK_NOT_FOUND); if (!issuccess) { log.debug("Network identifier {} is not existed", id); return Response.status(INTERNAL_SERVER_ERROR) .entity(NETWORK_ID_NOT_EXIST).build(); } return ok(issuccess.toString()).build(); } /** * Returns a collection of tenantNetworks. * * @param flag the flag * @param networkId network identifier * @param node the network json node * @return a collection of tenantNetworks */ public Iterable<TenantNetwork> changeJson2obj(String flag, TenantNetworkId networkId, JsonNode node) { checkNotNull(node, JSON_NOT_NULL); TenantNetwork network = null; ConcurrentMap<TenantNetworkId, TenantNetwork> networksMap = Maps .newConcurrentMap(); checkArgument(node.get("admin_state_up").isBoolean(), "admin_state_up should be boolean"); checkArgument(node.get("shared").isBoolean(), "shared should be boolean"); checkArgument(node.get("router:external").isBoolean(), "router:external should be boolean"); String name = node.get("name").asText(); boolean adminStateUp = node.get("admin_state_up").asBoolean(); String state = node.get("status").asText(); boolean shared = node.get("shared").asBoolean(); String tenantIdStr = node.get("tenant_id").asText(); boolean routerExternal = node.get("router:external").asBoolean(); String type = node.get("provider:network_type").asText(); String physicalNetwork = node.get("provider:physical_network").asText(); String segmentationIdStr = node.get("provider:segmentation_id").asText(); SegmentationId segmentationId = SegmentationId.segmentationId(segmentationIdStr); TenantId tenantId = TenantId.tenantId(tenantIdStr); if (segmentationIdStr == null || "null".equals(segmentationIdStr)) { segmentationId = get(VtnRscService.class).getL3vni(tenantId); } TenantNetworkId id = null; if (flag.equals(CREATE_NETWORK)) { id = TenantNetworkId.networkId(node.get("id").asText()); } else if (flag.equals(UPDATE_NETWORK)) { id = networkId; } network = new DefaultTenantNetwork( id, name, adminStateUp, isState(state), shared, tenantId, routerExternal, isType(type), PhysicalNetwork .physicalNetwork(physicalNetwork), segmentationId); networksMap.putIfAbsent(id, network); return Collections.unmodifiableCollection(networksMap.values()); } /** * Returns a collection of tenantNetworks. * * @param nodes the network jsonnodes * @return a collection of tenantNetworks */ public Iterable<TenantNetwork> changeJson2objs(JsonNode nodes) { checkNotNull(nodes, JSON_NOT_NULL); TenantNetwork network = null; ConcurrentMap<TenantNetworkId, TenantNetwork> networksMap = Maps .newConcurrentMap(); for (JsonNode node : nodes) { String id = node.get("id").asText(); String name = node.get("name").asText(); boolean adminStateUp = node.get("admin_state_up").asBoolean(); String state = node.get("status").asText(); boolean shared = node.get("shared").asBoolean(); String tenantIdStr = node.get("tenant_id").asText(); boolean routerExternal = node.get("router:external") .asBoolean(); String type = node.get("provider:network_type").asText(); String physicalNetwork = node.get("provider:physical_network").asText(); String segmentationIdStr = node.get("provider:segmentation_id").asText(); SegmentationId segmentationId = SegmentationId.segmentationId(segmentationIdStr); TenantId tenantId = TenantId.tenantId(tenantIdStr); if (segmentationIdStr == null || "null".equals(segmentationIdStr)) { segmentationId = get(VtnRscService.class).getL3vni(tenantId); } network = new DefaultTenantNetwork( TenantNetworkId.networkId(id), name, adminStateUp, isState(state), shared, tenantId, routerExternal, isType(type), PhysicalNetwork.physicalNetwork(physicalNetwork), segmentationId); networksMap.putIfAbsent(TenantNetworkId.networkId(id), network); } return Collections.unmodifiableCollection(networksMap.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; } }