xuzhang
Committed by Gerrit Code Review

[ONOS-2247]The implementation of subnet resource service.

Change-Id: I52cbd5c52ce2439122664e8c18b7603e61500d5c
......@@ -14,8 +14,7 @@
<artifactId>onos-app-vtnrsc</artifactId>
<packaging>bundle</packaging>
<properties>
<properties>
<onos.app.name>org.onosproject.vtnrsc</onos.app.name>
</properties>
<dependencies>
......@@ -34,50 +33,19 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
org.osgi.framework,
javax.ws.rs,
javax.ws.rs.core,
com.sun.jersey.api.core,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
com.fasterxml.jackson.databind,
com.fasterxml.jackson.databind.node,
com.fasterxml.jackson.core,
org.apache.karaf.shell.commands,
org.apache.commons.lang.math.*,
com.google.common.*,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*,
org.onlab.util.*,
org.jboss.netty.util.*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
......
......@@ -27,12 +27,12 @@ public interface AllocationPool {
*
* @return startIp
*/
IpAddress startIP();
IpAddress startIp();
/**
* The end address for the allocation pool.
*
* @return endIp
*/
IpAddress endIP();
IpAddress endIp();
}
......
/*
* 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.app.vtnrsc;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
import org.onlab.packet.IpAddress;
/**
* The continuous IP address range between the start address and the end address
* for the allocation pools.
*/
public final class DefaultAllocationPool implements AllocationPool {
private final IpAddress startIp;
private final IpAddress endIp;
/**
* Creates an AllocationPool by using the start IP address and the end IP
* address.
*
* @param startIp the start IP address of the allocation pool
* @param endIp the end IP address of the allocation pool
*/
public DefaultAllocationPool(IpAddress startIp, IpAddress endIp) {
checkNotNull(startIp, "StartIp cannot be null");
checkNotNull(endIp, "EndIp cannot be null");
this.startIp = startIp;
this.endIp = endIp;
}
@Override
public IpAddress startIp() {
return startIp;
}
@Override
public IpAddress endIp() {
return endIp;
}
@Override
public int hashCode() {
return Objects.hash(startIp, endIp);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultAllocationPool) {
final DefaultAllocationPool other = (DefaultAllocationPool) obj;
return Objects.equals(this.startIp, other.startIp)
&& Objects.equals(this.endIp, other.endIp);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this).add("startIp", startIp).add("endIp", endIp)
.toString();
}
}
/*
* 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.app.vtnrsc;
import static com.google.common.base.MoreObjects.toStringHelper;
import java.util.Objects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
/**
* Host route dictionaries for the subnet.
*/
public final class DefaultHostRoute implements HostRoute {
private final IpAddress nexthop;
private final IpPrefix destination;
/**
*
* Creates a DefaultHostRoute by using the next hop and the destination.
*
* @param nexthop of the DefaultHostRoute
* @param destination of the DefaultHostRoute
*/
public DefaultHostRoute(IpAddress nexthop, IpPrefix destination) {
this.nexthop = nexthop;
this.destination = destination;
}
@Override
public IpAddress nexthop() {
return nexthop;
}
@Override
public IpPrefix destination() {
return destination;
}
@Override
public String toString() {
return toStringHelper(this).add("nexthop", nexthop)
.add("destination", destination).toString();
}
@Override
public int hashCode() {
return Objects.hash(nexthop, destination);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultHostRoute) {
final DefaultHostRoute other = (DefaultHostRoute) obj;
return Objects.equals(this.nexthop, other.nexthop)
&& Objects.equals(this.destination, other.destination);
}
return false;
}
}
/*
* 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.app.vtnrsc;
import static com.google.common.base.MoreObjects.toStringHelper;
import java.util.Objects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpAddress.Version;
import org.onlab.packet.IpPrefix;
/**
* Default implementation of Subnet interface .
*/
public final class DefaultSubnet implements Subnet {
private final SubnetId id;
private final String subnetName;
private final TenantNetworkId networkId;
private final TenantId tenantId;
private final Version ipVersion;
private final IpPrefix cidr;
private final IpAddress gatewayIp;
private final boolean dhcpEnabled;
private final boolean shared;
private final Mode ipV6AddressMode;
private final Mode ipV6RaMode;
private final Iterable<HostRoute> hostRoutes;
private final Iterable<AllocationPool> allocationPools;
/**
* Creates a subnet object.
*
* @param id subnet identifier
* @param subnetName the name of subnet
* @param networkId network identifier
* @param tenantId tenant identifier
* @param cidr the cidr
* @param gatewayIp gateway ip
* @param dhcpEnabled dhcp enabled or not
* @param shared indicates whether this network is shared across all
* tenants, By default, only administrative user can change this
* value
* @param hostRoutes a collection of host routes
* @param ipV6AddressMode ipV6AddressMode
* @param ipV6RaMode ipV6RaMode
* @param allocationPoolsIt a collection of allocationPools
*/
public DefaultSubnet(SubnetId id, String subnetName,
TenantNetworkId networkId, TenantId tenantId,
Version ipVersion, IpPrefix cidr, IpAddress gatewayIp,
boolean dhcpEnabled, boolean shared,
Iterable<HostRoute> hostRoutes, Mode ipV6AddressMode,
Mode ipV6RaMode,
Iterable<AllocationPool> allocationPoolsIt) {
this.id = id;
this.subnetName = subnetName;
this.networkId = networkId;
this.tenantId = tenantId;
this.ipVersion = ipVersion;
this.cidr = cidr;
this.gatewayIp = gatewayIp;
this.dhcpEnabled = dhcpEnabled;
this.shared = shared;
this.ipV6AddressMode = ipV6AddressMode;
this.ipV6RaMode = ipV6RaMode;
this.hostRoutes = hostRoutes;
this.allocationPools = allocationPoolsIt;
}
@Override
public SubnetId id() {
return id;
}
@Override
public String subnetName() {
return subnetName;
}
@Override
public TenantNetworkId networkId() {
return networkId;
}
@Override
public TenantId tenantId() {
return tenantId;
}
@Override
public Version ipVersion() {
return ipVersion;
}
@Override
public IpPrefix cidr() {
return cidr;
}
@Override
public IpAddress gatewayIp() {
return gatewayIp;
}
@Override
public boolean dhcpEnabled() {
return dhcpEnabled;
}
@Override
public boolean shared() {
return shared;
}
@Override
public Iterable<HostRoute> hostRoutes() {
return hostRoutes;
}
@Override
public Mode ipV6AddressMode() {
return ipV6AddressMode;
}
@Override
public Mode ipV6RaMode() {
return ipV6RaMode;
}
@Override
public Iterable<AllocationPool> allocationPools() {
return allocationPools;
}
@Override
public int hashCode() {
return Objects.hash(id, subnetName, ipVersion, cidr, gatewayIp,
dhcpEnabled, shared, tenantId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultSubnet) {
final DefaultSubnet that = (DefaultSubnet) obj;
return Objects.equals(this.id, that.id)
&& Objects.equals(this.subnetName, that.subnetName)
&& Objects.equals(this.ipVersion, that.ipVersion)
&& Objects.equals(this.cidr, that.cidr)
&& Objects.equals(this.shared, that.shared)
&& Objects.equals(this.gatewayIp, that.gatewayIp)
&& Objects.equals(this.dhcpEnabled, that.dhcpEnabled);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this).add("id", id).add("subnetName", subnetName)
.add("ipVersion", ipVersion).add("cidr", cidr)
.add("shared", shared).add("gatewayIp", gatewayIp)
.add("dhcpEnabled", dhcpEnabled).toString();
}
}
......@@ -32,9 +32,9 @@ public interface Subnet {
}
/**
* Returns the ID of the subnet.
* Returns the subnet identifier.
*
* @return id
* @return identifier
*/
SubnetId id();
......@@ -46,18 +46,16 @@ public interface Subnet {
String subnetName();
/**
* Returns the ID of the attached network.
* Returns the network identifier.
*
* @return networkID
* @return the network identifier
*/
TenantNetworkId networkId();
/**
* Returns the The ID of the tenant who owns the network. Only
* administrative users can specify a tenant ID other than their own. You
* cannot change this value through authorization policies.
* Returns tenant identifier.
*
* @return tenantID
* @return the tenant identifier
*/
TenantId tenantId();
......@@ -76,31 +74,31 @@ public interface Subnet {
IpPrefix cidr();
/**
* Returns the gateway IP address..
* Returns the gateway IP address.
*
* @return gatewayIP
* @return gatewayIp
*/
IpAddress gatewayIp();
/**
* Returns true if DHCP is enabled and return false if DHCP is disabled.
*
* @return dhcpEnabled
* @return true or false
*/
boolean dhcpEnabled();
/**
* Indicates whether this tenantNetwork is shared across all tenants. By
* default,only administrative user can change this value.
* default, only administrative user can change this value.
*
* @return shared
* @return true or false
*/
boolean shared();
/**
* Returns an iterable collections of hostRoutes.
* Returns a collection of hostRoutes.
*
* @return hostRoutes collection
* @return a collection of hostRoutes
*/
Iterable<HostRoute> hostRoutes();
......@@ -108,7 +106,8 @@ public interface Subnet {
* Returns the ipV6AddressMode. A valid value is dhcpv6-stateful,
* dhcpv6-stateless, or slaac.
*
* @return ipV6AddressMode
* @return ipV6AddressMode whose value is dhcpv6-stateful, dhcpv6-stateless
* or slaac
*/
Mode ipV6AddressMode();
......@@ -116,15 +115,15 @@ public interface Subnet {
* Returns the ipV6RaMode.A valid value is dhcpv6-stateful,
* dhcpv6-stateless, or slaac.
*
* @return ipV6RaMode
* @return ipV6RaMode whose value is dhcpv6-stateful, dhcpv6-stateless or
* slaac
*/
Mode ipV6RaMode();
/**
* Returns an iterable collection of allocation_pools.
* Returns a collection of allocation_pools.
*
* @return allocationPools collection
* @return a collection of allocationPools
*/
Iterable<AllocationPool> allocationPools();
}
......
......@@ -20,7 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
* Immutable representation of a subnet identity.
* Immutable representation of a subnet identifier.
*/
public final class SubnetId {
......@@ -33,15 +33,24 @@ public final class SubnetId {
}
/**
* Creates a subnet identifier.
* Creates a Subnet identifier.
*
* @param subnetId subnet identifier
* @return SubnetId SubnetId
* @param subnetId the subnet identifier
* @return the subnet identifier
*/
public static SubnetId subnetId(String subnetId) {
return new SubnetId(subnetId);
}
/**
* Returns the subnet identifier.
*
* @return the subnet identifier
*/
public String subnetId() {
return subnetId;
}
@Override
public int hashCode() {
return Objects.hash(subnetId);
......@@ -64,5 +73,4 @@ public final class SubnetId {
public String toString() {
return subnetId;
}
}
......
/*
* 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.app.vtnrsc.subnet.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.KryoNamespace;
import org.onosproject.app.vtnrsc.Subnet;
import org.onosproject.app.vtnrsc.SubnetId;
import org.onosproject.app.vtnrsc.subnet.SubnetService;
import org.onosproject.app.vtnrsc.tenantnetwork.TenantNetworkService;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.MultiValuedTimestamp;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
import org.slf4j.Logger;
/**
* Provides implementation of the Subnet service.
*/
@Component(immediate = true)
@Service
public class SubnetManager implements SubnetService {
private static final String SUBNET_ID_NULL = "Subnet ID cannot be null";
private static final String SUBNET_NOT_NULL = "Subnet cannot be null";
private final Logger log = getLogger(getClass());
private EventuallyConsistentMap<SubnetId, Subnet> subnetStore;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TenantNetworkService tenantNetworkService;
@Activate
public void activate() {
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
.register(MultiValuedTimestamp.class);
subnetStore = storageService
.<SubnetId, Subnet>eventuallyConsistentMapBuilder()
.withName("all_subnet").withSerializer(serializer)
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
log.info("SubnetManager started");
}
@Deactivate
public void deactivate() {
subnetStore.destroy();
log.info("SubnetManager stopped");
}
@Override
public Iterable<Subnet> getSubnets() {
return Collections.unmodifiableCollection(subnetStore.values());
}
@Override
public Subnet getSubnet(SubnetId subnetId) {
checkNotNull(subnetId, SUBNET_ID_NULL);
return subnetStore.get(subnetId);
}
@Override
public boolean exists(SubnetId subnetId) {
checkNotNull(subnetId, SUBNET_ID_NULL);
return subnetStore.containsKey(subnetId);
}
@Override
public boolean createSubnets(Iterable<Subnet> subnets) {
checkNotNull(subnets, SUBNET_NOT_NULL);
for (Subnet subnet : subnets) {
if (!tenantNetworkService.exists(subnet.networkId())) {
log.debug("The network identifier that the subnet {} belong to is not exist",
subnet.networkId().toString(), subnet.id().toString());
return false;
}
subnetStore.put(subnet.id(), subnet);
if (!subnetStore.containsKey(subnet.id())) {
log.debug("The identified subnet whose identifier is {} create failed",
subnet.id().toString());
return false;
}
}
return true;
}
@Override
public boolean updateSubnets(Iterable<Subnet> subnets) {
checkNotNull(subnets, SUBNET_NOT_NULL);
if (subnets != null) {
for (Subnet subnet : subnets) {
if (!subnetStore.containsKey(subnet.id())) {
log.debug("The subnet is not exist whose identifier is {}",
subnet.id().toString());
return false;
}
subnetStore.put(subnet.id(), subnet);
if (!subnet.equals(subnetStore.get(subnet.id()))) {
log.debug("The subnet is updated failed whose identifier is {}",
subnet.id().toString());
return false;
}
}
}
return true;
}
@Override
public boolean removeSubnets(Iterable<SubnetId> subnetIds) {
checkNotNull(subnetIds, SUBNET_ID_NULL);
if (subnetIds != null) {
for (SubnetId subnetId : subnetIds) {
subnetStore.remove(subnetId);
if (subnetStore.containsKey(subnetId)) {
log.debug("The subnet created is failed whose identifier is {}",
subnetId.toString());
return false;
}
}
}
return true;
}
}
/*
* 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.app.vtnrsc.web;
import static com.google.common.base.Preconditions.checkNotNull;
import org.onosproject.app.vtnrsc.AllocationPool;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Subnet AllocationPool codec.
*/
public final class AllocationPoolsCodec extends JsonCodec<AllocationPool> {
@Override
public ObjectNode encode(AllocationPool alocPool, CodecContext context) {
checkNotNull(alocPool, "AllocationPools cannot be null");
ObjectNode result = context.mapper().createObjectNode()
.put("start", alocPool.startIp().toString())
.put("end", alocPool.endIp().toString());
return result;
}
}
/*
* 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.app.vtnrsc.web;
import static com.google.common.base.Preconditions.checkNotNull;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.app.vtnrsc.HostRoute;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Subnet HostRoute codec.
*/
public final class HostRoutesCodec extends JsonCodec<HostRoute> {
@Override
public ObjectNode encode(HostRoute hostRoute, CodecContext context) {
checkNotNull(hostRoute, "HostRoute cannot be null");
ObjectNode result = context.mapper().createObjectNode()
.put("nexthop", hostRoute.nexthop().toString())
.put("destination", hostRoute.destination().toString());
return result;
}
}
/*
* 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.app.vtnrsc.web;
import static com.google.common.base.Preconditions.checkNotNull;
import org.onosproject.app.vtnrsc.Subnet;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Subnet JSON codec.
*/
public final class SubnetCodec extends JsonCodec<Subnet> {
@Override
public ObjectNode encode(Subnet subnet, CodecContext context) {
checkNotNull(subnet, "Subnet cannot be null");
ObjectNode result = context.mapper().createObjectNode()
.put("id", subnet.id().toString())
.put("gate_ip", subnet.gatewayIp().toString())
.put("network_id", subnet.networkId().toString())
.put("name", subnet.subnetName().toString())
.put("ip_version", subnet.ipVersion().toString())
.put("cidr", subnet.cidr().toString())
.put("shared", subnet.shared())
.put("enabled_dchp", subnet.dhcpEnabled())
.put("tenant_id", subnet.tenantId().toString());
result.set("alloction_pools", new AllocationPoolsCodec().encode(subnet
.allocationPools(), context));
result.set("host_routes",
new HostRoutesCodec().encode(subnet.hostRoutes(), context));
return result;
}
}
/*
* 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.INTERNAL_SERVER_ERROR;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
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.core.MediaType;
import javax.ws.rs.core.Response;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpAddress.Version;
import org.onlab.packet.IpPrefix;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.app.vtnrsc.AllocationPool;
import org.onosproject.app.vtnrsc.DefaultAllocationPool;
import org.onosproject.app.vtnrsc.DefaultHostRoute;
import org.onosproject.app.vtnrsc.DefaultSubnet;
import org.onosproject.app.vtnrsc.HostRoute;
import org.onosproject.app.vtnrsc.Subnet;
import org.onosproject.app.vtnrsc.Subnet.Mode;
import org.onosproject.app.vtnrsc.SubnetId;
import org.onosproject.app.vtnrsc.TenantId;
import org.onosproject.app.vtnrsc.TenantNetworkId;
import org.onosproject.app.vtnrsc.subnet.SubnetService;
import org.onosproject.app.vtnrsc.web.SubnetCodec;
import org.onosproject.rest.AbstractWebResource;
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.Maps;
@Path("subnets")
public class SubnetWebResource extends AbstractWebResource {
private final Logger log = LoggerFactory.getLogger(SubnetWebResource.class);
public static final String SUBNET_NOT_CREATE = "Subnets is failed to create!";
public static final String SUBNET_NOT_FOUND = "Subnets is failed to update!";
public static final String JSON_NOT_NULL = "JsonNode can not be null";
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response listSubnets() {
Iterable<Subnet> subnets = get(SubnetService.class).getSubnets();
ObjectNode result = new ObjectMapper().createObjectNode();
result.set("subnets", new SubnetCodec().encode(subnets, this));
return ok(result.toString()).build();
}
@GET
@Path("{subnetUUID}")
@Produces(MediaType.APPLICATION_JSON)
public Response getSubnet(@PathParam("subnetUUID") String id) {
if (!get(SubnetService.class).exists(SubnetId.subnetId(id))) {
return ok("the subnet does not exists").build();
}
Subnet sub = nullIsNotFound(get(SubnetService.class)
.getSubnet(SubnetId.subnetId(id)),
SUBNET_NOT_FOUND);
ObjectNode result = new ObjectMapper().createObjectNode();
result.set("subnet", new SubnetCodec().encode(sub, this));
return ok(result.toString()).build();
}
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response createSubnet(final InputStream input) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode subnode = mapper.readTree(input);
Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
Boolean result = nullIsNotFound((get(SubnetService.class)
.createSubnets(subnets)),
SUBNET_NOT_CREATE);
if (!result) {
return Response.status(204).entity(SUBNET_NOT_CREATE).build();
}
return Response.status(202).entity(result.toString()).build();
} catch (Exception e) {
return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
.build();
}
}
@PUT
@Path("{subnetUUID}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response updateSubnet(@PathParam("id") String id,
final InputStream input) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode subnode = mapper.readTree(input);
Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
Boolean result = nullIsNotFound(get(SubnetService.class)
.updateSubnets(subnets), SUBNET_NOT_FOUND);
if (!result) {
return Response.status(204).entity(SUBNET_NOT_FOUND).build();
}
return Response.status(203).entity(result.toString()).build();
} catch (Exception e) {
return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
.build();
}
}
@Path("{subnetUUID}")
@DELETE
public Response deleteSingleSubnet(@PathParam("subnetUUID") String id)
throws IOException {
try {
SubnetId subId = SubnetId.subnetId(id);
Set<SubnetId> subIds = new HashSet<SubnetId>();
subIds.add(subId);
get(SubnetService.class).removeSubnets(subIds);
return Response.status(201).entity("SUCCESS").build();
} catch (Exception e) {
return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
.build();
}
}
private Iterable<Subnet> createOrUpdateByInputStream(JsonNode subnode) {
checkNotNull(subnode, JSON_NOT_NULL);
Iterable<Subnet> subnets = null;
JsonNode subnetNodes = subnode.get("subnets");
if (subnetNodes == null) {
subnetNodes = subnode.get("subnet");
}
log.debug("subnetNodes is {}", subnetNodes.toString());
if (subnetNodes.isArray()) {
subnets = changeJsonToSubs(subnetNodes);
} else {
subnets = changeJsonToSub(subnetNodes);
}
return subnets;
}
/**
* Returns a collection of subnets from subnetNodes.
*
* @param subnetNodes the subnet json node
* @return subnets a collection of subnets
*/
public Iterable<Subnet> changeJsonToSubs(JsonNode subnetNodes) {
checkNotNull(subnetNodes, JSON_NOT_NULL);
Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
for (JsonNode subnetNode : subnetNodes) {
if (subnetNode.hasNonNull("id")) {
return null;
}
SubnetId id = SubnetId.subnetId(subnetNode.get("id").asText());
String subnetName = subnetNode.get("name").asText();
TenantId tenantId = TenantId.tenantId(subnetNode.get("tenant_id")
.asText());
TenantNetworkId networkId = TenantNetworkId.networkId(subnetNode
.get("network_id").asText());
Version ipVersion = Version.valueOf(subnetNode.get("ip_version")
.asText());
IpPrefix cidr = IpPrefix.valueOf(subnetNode.get("cidr").asText());
IpAddress gatewayIp = IpAddress.valueOf(subnetNode
.get("gateway_ip").asText());
Boolean dhcpEnabled = subnetNode.get("enable_dhcp").asBoolean();
Boolean shared = subnetNode.get("shared").asBoolean();
JsonNode hostRoutes = subnetNode.get("host_routes");
Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
JsonNode allocationPools = subnetNode.get("allocation_pools");
Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);
Mode ipV6AddressMode = Mode.valueOf(subnetNode
.get("ipv6_address_mode").asText());
Mode ipV6RaMode = Mode.valueOf(subnetNode.get("ipv6_ra_mode")
.asText());
Subnet subnet = new DefaultSubnet(id, subnetName, networkId,
tenantId, ipVersion, cidr,
gatewayIp, dhcpEnabled, shared,
hostRoutesIt, ipV6AddressMode,
ipV6RaMode, allocationPoolsIt);
subMap.put(id, subnet);
}
return Collections.unmodifiableCollection(subMap.values());
}
/**
* Returns a collection of subnets from subnetNodes.
*
* @param subnetNodes the subnet json node
* @return subnets a collection of subnets
*/
public Iterable<Subnet> changeJsonToSub(JsonNode subnetNodes) {
checkNotNull(subnetNodes, JSON_NOT_NULL);
Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
SubnetId id = SubnetId.subnetId(subnetNodes.get("id").asText());
String subnetName = subnetNodes.get("name").asText();
TenantId tenantId = TenantId.tenantId(subnetNodes.get("tenant_id")
.asText());
TenantNetworkId networkId = TenantNetworkId.networkId(subnetNodes
.get("network_id").asText());
Version ipVersion = Version.valueOf(subnetNodes.get("ip_version")
.asText());
IpPrefix cidr = IpPrefix.valueOf(subnetNodes.get("cidr").asText());
IpAddress gatewayIp = IpAddress.valueOf(subnetNodes.get("gateway_ip")
.asText());
Boolean dhcpEnabled = subnetNodes.get("enable_dhcp").asBoolean();
Boolean shared = subnetNodes.get("shared").asBoolean();
JsonNode hostRoutes = subnetNodes.get("host_routes");
Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
JsonNode allocationPools = subnetNodes.get("allocation_pools");
Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);
Mode ipV6AddressMode = Mode.valueOf(subnetNodes
.get("ipv6_address_mode").asText());
Mode ipV6RaMode = Mode
.valueOf(subnetNodes.get("ipv6_ra_mode").asText());
Subnet subnet = new DefaultSubnet(id, subnetName, networkId, tenantId,
ipVersion, cidr, gatewayIp,
dhcpEnabled, shared, hostRoutesIt,
ipV6AddressMode, ipV6RaMode,
allocationPoolsIt);
subMap.put(id, subnet);
return Collections.unmodifiableCollection(subMap.values());
}
/**
* Changes JsonNode alocPools to a collection of the alocPools.
*
* @param allocationPools the allocationPools JsonNode
* @return a collection of allocationPools
*/
public Iterable<AllocationPool> jsonNodeToAllocationPools(JsonNode allocationPools) {
checkNotNull(allocationPools, JSON_NOT_NULL);
ConcurrentMap<Integer, AllocationPool> alocplMaps = Maps
.newConcurrentMap();
Integer i = 0;
for (JsonNode node : allocationPools) {
IpAddress startIp = IpAddress.valueOf(node.get("start").asText());
IpAddress endIp = IpAddress.valueOf(node.get("end").asText());
AllocationPool alocPls = new DefaultAllocationPool(startIp, endIp);
alocplMaps.putIfAbsent(i, alocPls);
i++;
}
return Collections.unmodifiableCollection(alocplMaps.values());
}
/**
* Changes hostRoutes JsonNode to a collection of the hostRoutes.
*
* @param hostRoutes the hostRoutes json node
* @return a collection of hostRoutes
*/
public Iterable<HostRoute> jsonNodeToHostRoutes(JsonNode hostRoutes) {
checkNotNull(hostRoutes, JSON_NOT_NULL);
ConcurrentMap<Integer, HostRoute> hostRouteMaps = Maps
.newConcurrentMap();
Integer i = 0;
for (JsonNode node : hostRoutes) {
IpAddress nexthop = IpAddress.valueOf(node.get("nexthop").asText());
IpPrefix destination = IpPrefix.valueOf(node.get("destination")
.asText());
HostRoute hostRoute = new DefaultHostRoute(nexthop, destination);
hostRouteMaps.putIfAbsent(i, hostRoute);
i++;
}
return Collections.unmodifiableCollection(hostRouteMaps.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;
}
}
......@@ -30,7 +30,9 @@
<init-param>
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>
org.onosproject.vtnweb.resources.TenantNetworkWebResource
org.onosproject.vtnweb.resources.TenantNetworkWebResource,
org.onosproject.vtnweb.resources.SubnetWebResource,
org.onosproject.vtnweb.resources.VirtualPortWebResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
......