Hyunsun Moon

[Falcon] CORD-366 Implemented CORD service dependency API and pipeline

Done
- Implement service dependency APIs
- Populate or remove basic tenant connectivity rules when VM created or removed
- Populate direct/indirect service access rules when service dependency created
- Remove service dependency rules

Todo
- Add/remove bucket to proper group when a VM is created or terminated
- Populate service dependency rules for existing VMs when service is activated
- Cleanup flow rules remove

Change-Id: I1daaf7ac9b41d7f2694605cb9b75f12d42144dbd
......@@ -18,8 +18,18 @@ package org.onosproject.cordvtn;
import com.google.common.base.MoreObjects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.net.Host;
import org.onosproject.openstackswitching.OpenstackNetwork;
import org.onosproject.openstackswitching.OpenstackSubnet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.cordvtn.CordService.ServiceType.*;
import static org.onosproject.cordvtn.CordService.ServiceType.PRIVATE;
import static org.onosproject.cordvtn.CordService.ServiceType.PUBLIC_INDIRECT;
public final class CordService {
......@@ -36,23 +46,25 @@ public final class CordService {
private final ServiceType serviceType;
private final IpPrefix serviceIpRange;
private final IpAddress serviceIp;
private final Map<Host, IpAddress> hosts;
private final Set<CordServiceId> tenantServices;
/**
* Default constructor.
*
* @param id service id, which is identical to OpenStack network id
* @param segmentationId segmentation id, which is identical to VNI
* @param serviceType service type
* @param serviceIpRange service ip range
* @param serviceIp service ip
* @param vNet OpenStack network
* @param hosts host and tunnel ip map
* @param tenantServices list of tenant service ids
*/
public CordService(CordServiceId id, long segmentationId, ServiceType serviceType,
IpPrefix serviceIpRange, IpAddress serviceIp) {
this.id = id;
this.segmentationId = segmentationId;
this.serviceType = serviceType;
this.serviceIpRange = serviceIpRange;
this.serviceIp = serviceIp;
public CordService(OpenstackNetwork vNet, OpenstackSubnet subnet,
Map<Host, IpAddress> hosts, Set<CordServiceId> tenantServices) {
this.id = CordServiceId.of(vNet.id());
this.segmentationId = Long.parseLong(vNet.segmentId());
this.serviceType = getServiceType(vNet.name());
this.serviceIpRange = IpPrefix.valueOf(subnet.cidr());
this.serviceIp = IpAddress.valueOf(subnet.gatewayIp());
this.hosts = hosts;
this.tenantServices = tenantServices;
}
/**
......@@ -100,6 +112,24 @@ public final class CordService {
return serviceIp;
}
/**
* Returns hosts associated with this service.
*
* @return list of hosts
*/
public Map<Host, IpAddress> hosts() {
return hosts;
}
/**
* Returns tenant service IDs.
*
* @return list of tenant service id
*/
public Set<CordServiceId> tenantServices() {
return tenantServices;
}
@Override
public int hashCode() {
return Objects.hash(id);
......@@ -125,6 +155,33 @@ public final class CordService {
.add("serviceType", serviceType)
.add("serviceIpRange", serviceIpRange)
.add("serviceIp", serviceIp)
.add("tenantServices", tenantServices)
.toString();
}
/**
* Returns network type from network name.
* It assumes that network name contains network type.
*
* @param netName network name
* @return network type, or null if it doesn't match any type
*/
private ServiceType getServiceType(String netName) {
checkNotNull(netName);
String name = netName.toUpperCase();
if (name.contains(PRIVATE_DIRECT.toString())) {
return PRIVATE_DIRECT;
} else if (name.contains(PRIVATE_INDIRECT.toString())) {
return PRIVATE_INDIRECT;
} else if (name.contains(PUBLIC_DIRECT.toString())) {
return PUBLIC_DIRECT;
} else if (name.contains(PUBLIC_INDIRECT.toString())) {
return PUBLIC_INDIRECT;
} else if (name.contains(PRIVATE.toString())) {
return PRIVATE;
} else {
return null;
}
}
}
......
......@@ -69,15 +69,16 @@ public interface CordVtnService {
/**
* Creates dependencies for a given tenant service.
*
* @param tenantCordServiceId id of the service which has a dependency
* @param providerCordServiceId id of the service which provide dependency
* @param tServiceId id of the service which has a dependency
* @param pServiceId id of the service which provide dependency
*/
void createServiceDependency(CordServiceId tenantCordServiceId, CordServiceId providerCordServiceId);
void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId);
/**
* Removes all dependencies from a given tenant service.
*
* @param tenantCordServiceId id of the service which has a dependency
* @param tServiceId id of the service which has a dependency
* @param pServiceId id of the service which provide dependency
*/
void removeServiceDependency(CordServiceId tenantCordServiceId);
void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId);
}
......
/*
* Copyright 2014-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.cordvtn;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.net.Port;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Contains destination information.
*/
public final class DestinationInfo {
private final Port output;
private final List<IpAddress> ip;
private final MacAddress mac;
private final IpAddress remoteIp;
private final long tunnelId;
/**
* Creates a new destination information.
*
* @param output output port
* @param ip destination ip address
* @param mac destination mac address
* @param remoteIp tunnel remote ip address
* @param tunnelId segment id
*/
public DestinationInfo(Port output, List<IpAddress> ip, MacAddress mac,
IpAddress remoteIp, long tunnelId) {
this.output = checkNotNull(output);
this.ip = ip;
this.mac = mac;
this.remoteIp = remoteIp;
this.tunnelId = tunnelId;
}
/**
* Returns output port.
*
* @return port
*/
public Port output() {
return output;
}
/**
* Returns destination ip addresses.
*
* @return list of ip address
*/
public List<IpAddress> ip() {
return ip;
}
/**
* Returns destination mac address.
*
* @return mac address
*/
public MacAddress mac() {
return mac;
}
/**
* Returns tunnel remote ip address.
*
* @return ip address
*/
public IpAddress remoteIp() {
return remoteIp;
}
/**
* Returns tunnel id.
*
* @return tunnel id
*/
public long tunnelId() {
return tunnelId;
}
/**
* Returns a new destination info builder.
*
* @return destination info builder
*/
public static DestinationInfo.Builder builder(Port output) {
return new Builder(output);
}
/**
* DestinationInfo builder class.
*/
public static final class Builder {
private final Port output;
private List<IpAddress> ip;
private MacAddress mac;
private IpAddress remoteIp;
private long tunnelId;
/**
* Creates a new destination information builder.
*
* @param output output port
*/
public Builder(Port output) {
this.output = checkNotNull(output, "Output port cannot be null");
}
/**
* Sets the destination ip address.
*
* @param ip ip address
* @return destination info builder
*/
public Builder setIp(List<IpAddress> ip) {
this.ip = checkNotNull(ip, "IP cannot be null");
return this;
}
/**
* Sets the destination mac address.
*
* @param mac mac address
* @return destination info builder
*/
public Builder setMac(MacAddress mac) {
this.mac = checkNotNull(mac, "MAC address cannot be null");
return this;
}
/**
* Sets the tunnel remote ip address.
*
* @param remoteIp ip address
* @return destination info builder
*/
public Builder setRemoteIp(IpAddress remoteIp) {
this.remoteIp = checkNotNull(remoteIp, "Remote IP address cannot be null");
return this;
}
/**
* Sets the tunnel id.
*
* @param tunnelId tunnel id
* @return destination info builder
*/
public Builder setTunnelId(long tunnelId) {
this.tunnelId = checkNotNull(tunnelId, "Tunnel ID cannot be null");
return this;
}
/**
* Build a destination information.
*
* @return destination info object
*/
public DestinationInfo build() {
return new DestinationInfo(this);
}
}
private DestinationInfo(Builder builder) {
output = builder.output;
ip = builder.ip;
mac = builder.mac;
remoteIp = builder.remoteIp;
tunnelId = builder.tunnelId;
}
}
......@@ -58,14 +58,16 @@ public class ServiceDependencyWebResource extends AbstractWebResource {
/**
* Removes service dependencies.
*
* @param serviceId service id
* @param tServiceId tenant service id
* @param pServiceId provider service id
* @return 200 OK, or 400 Bad Request
*/
@DELETE
@Path("{serviceId}")
@Path("{tenantServiceId}/{providerServiceId}")
@Produces(MediaType.APPLICATION_JSON)
public Response removeServiceDependency(@PathParam("serviceId") String serviceId) {
service.removeServiceDependency(CordServiceId.of(serviceId));
public Response removeServiceDependency(@PathParam("tenantServiceId") String tServiceId,
@PathParam("providerServiceId") String pServiceId) {
service.removeServiceDependency(CordServiceId.of(tServiceId), CordServiceId.of(pServiceId));
return Response.status(Response.Status.OK).build();
}
......