jiangrui
Committed by Gerrit Code Review

[ONOS-2820] add implementation of floatingIpService api

Change-Id: I65a2643dcf0443fa4ae0cd647bcb42fa9e2a6e44
/*
* 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.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;
/**
* Default implementation of FloatingIp interface.
*/
public final class DefaultFloatingIp implements FloatingIp {
private final FloatingIpId id;
private final TenantId tenantId;
private final TenantNetworkId networkId;
private final VirtualPortId portId;
private final RouterId routerId;
private final IpAddress floatingIp;
private final IpAddress fixedIp;
private final Status status;
/**
*
* Creates a floating Ip object.
*
* @param id floatingIp identifier
* @param tenantId tenant identifier
* @param networkId the identifier of network associated with the floating Ip
* @param portId port identifier
* @param routerId router identifier
* @param floatingIp floatingIp address
* @param fixedIp the fixed Ip associated with the floating Ip
* @param status the floating Ip status
*/
public DefaultFloatingIp(FloatingIpId id, TenantId tenantId,
TenantNetworkId networkId, VirtualPortId portId,
RouterId routerId, IpAddress floatingIp,
IpAddress fixedIp, Status status) {
this.id = checkNotNull(id, "id cannot be null");
this.tenantId = checkNotNull(tenantId, "tenantId cannot be null");
this.networkId = checkNotNull(networkId, "networkId cannot be null");
this.portId = portId;
this.routerId = routerId;
this.floatingIp = checkNotNull(floatingIp, "floatingIp cannot be null");
this.fixedIp = fixedIp;
this.status = checkNotNull(status, "status cannot be null");
}
@Override
public FloatingIpId id() {
return id;
}
@Override
public TenantId tenantId() {
return tenantId;
}
@Override
public TenantNetworkId networkId() {
return networkId;
}
@Override
public VirtualPortId portId() {
return portId;
}
@Override
public RouterId routerId() {
return routerId;
}
@Override
public IpAddress floatingIp() {
return floatingIp;
}
@Override
public IpAddress fixedIp() {
return fixedIp;
}
@Override
public Status status() {
return status;
}
@Override
public int hashCode() {
return Objects.hash(id, tenantId, networkId, portId, routerId,
floatingIp, fixedIp, status);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultFloatingIp) {
final DefaultFloatingIp that = (DefaultFloatingIp) obj;
return Objects.equals(this.id, that.id)
&& Objects.equals(this.tenantId, that.tenantId)
&& Objects.equals(this.networkId, that.networkId)
&& Objects.equals(this.portId, that.portId)
&& Objects.equals(this.routerId, that.routerId)
&& Objects.equals(this.floatingIp, that.floatingIp)
&& Objects.equals(this.fixedIp, that.fixedIp)
&& Objects.equals(this.status, that.status);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this).add("id", id).add("tenantId", tenantId)
.add("networkId", networkId).add("portId", portId)
.add("routerId", routerId).add("floatingIp", floatingIp)
.add("fixedIp", fixedIp).add("floatingIpStatus", status)
.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.vtnrsc.floatingip.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
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.packet.IpAddress;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapEvent;
import org.onosproject.store.service.EventuallyConsistentMapListener;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
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.FloatingIpEvent;
import org.onosproject.vtnrsc.floatingip.FloatingIpListener;
import org.onosproject.vtnrsc.floatingip.FloatingIpService;
import org.onosproject.vtnrsc.router.RouterService;
import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;
import com.google.common.collect.Sets;
/**
* Provides implementation of the FloatingIp service.
*/
@Component(immediate = true)
@Service
public class FloatingIpManager implements FloatingIpService {
private static final String FLOATINGIP_ID_NOT_NULL = "Floatingip ID cannot be null";
private static final String FLOATINGIP_NOT_NULL = "Floatingip cannot be null";
private static final String FLOATINGIP = "vtn-floatingip-store";
private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
private static final String LISTENER_NOT_NULL = "Listener cannot be null";
private static final String EVENT_NOT_NULL = "event cannot be null";
private final Logger log = getLogger(getClass());
private final Set<FloatingIpListener> listeners = Sets
.newCopyOnWriteArraySet();
private EventuallyConsistentMapListener<FloatingIpId, FloatingIp> floatingIpListener =
new InnerFloatingIpStoreListener();
protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpStore;
protected ApplicationId appId;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TenantNetworkService tenantNetworkService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected VirtualPortService virtualPortService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected RouterService routerService;
@Activate
public void activate() {
appId = coreService.registerApplication(VTNRSC_APP);
KryoNamespace.Builder serializer = KryoNamespace
.newBuilder()
.register(KryoNamespaces.API)
.register(FloatingIp.class, FloatingIpId.class,
TenantNetworkId.class, TenantId.class,
FloatingIp.Status.class, RouterId.class,
VirtualPortId.class, DefaultFloatingIp.class);
floatingIpStore = storageService
.<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
.withName(FLOATINGIP).withSerializer(serializer)
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
floatingIpStore.addListener(floatingIpListener);
log.info("Started");
}
@Deactivate
public void deactivate() {
floatingIpStore.removeListener(floatingIpListener);
floatingIpStore.destroy();
listeners.clear();
log.info("Stopped");
}
@Override
public Collection<FloatingIp> getFloatingIps() {
return Collections.unmodifiableCollection(floatingIpStore.values());
}
@Override
public FloatingIp getFloatingIp(FloatingIpId floatingIpId) {
checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
return floatingIpStore.get(floatingIpId);
}
@Override
public boolean exists(FloatingIpId floatingIpId) {
checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
return floatingIpStore.containsKey(floatingIpId);
}
@Override
public boolean floatingIpIsUsed(IpAddress floatingIpAddr,
FloatingIpId floatingIpId) {
checkNotNull(floatingIpAddr, "Floating IP address cannot be null");
checkNotNull(floatingIpId, "Floating IP Id cannot be null");
Collection<FloatingIp> floatingIps = getFloatingIps();
for (FloatingIp floatingIp : floatingIps) {
if (floatingIp.floatingIp().equals(floatingIpAddr)
&& !floatingIp.id().equals(floatingIpId)) {
return true;
}
}
return false;
}
@Override
public boolean fixedIpIsUsed(IpAddress fixedIpAddr, TenantId tenantId,
FloatingIpId floatingIpId) {
checkNotNull(fixedIpAddr, "Fixed IP address cannot be null");
checkNotNull(tenantId, "Tenant Id cannot be null");
checkNotNull(floatingIpId, "Floating IP Id cannot be null");
Collection<FloatingIp> floatingIps = getFloatingIps();
for (FloatingIp floatingIp : floatingIps) {
IpAddress fixedIp = floatingIp.fixedIp();
if (fixedIp != null) {
if (fixedIp.equals(fixedIpAddr)
&& floatingIp.tenantId().equals(tenantId)
&& !floatingIp.id().equals(floatingIpId)) {
return true;
}
}
}
return false;
}
@Override
public boolean createFloatingIps(Collection<FloatingIp> floatingIps) {
checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
boolean result = true;
for (FloatingIp floatingIp : floatingIps) {
verifyFloatingIpData(floatingIp);
if (floatingIp.portId() != null) {
floatingIpStore.put(floatingIp.id(), floatingIp);
if (!floatingIpStore.containsKey(floatingIp.id())) {
log.debug("The floating Ip is created failed whose identifier is {}",
floatingIp.id().toString());
result = false;
}
} else {
FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
if (oldFloatingIp != null) {
floatingIpStore.remove(floatingIp.id(), oldFloatingIp);
if (floatingIpStore.containsKey(floatingIp.id())) {
log.debug("The floating Ip is created failed whose identifier is {}",
floatingIp.id().toString());
result = false;
}
}
}
}
return result;
}
@Override
public boolean updateFloatingIps(Collection<FloatingIp> floatingIps) {
checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
boolean result = true;
if (floatingIps != null) {
for (FloatingIp floatingIp : floatingIps) {
verifyFloatingIpData(floatingIp);
if (floatingIp.portId() != null) {
floatingIpStore.put(floatingIp.id(), floatingIp);
if (!floatingIpStore.containsKey(floatingIp.id())) {
log.debug("The floating Ip is updated failed whose identifier is {}",
floatingIp.id().toString());
result = false;
}
} else {
FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp
.id());
if (oldFloatingIp != null) {
floatingIpStore.remove(floatingIp.id(), oldFloatingIp);
if (floatingIpStore.containsKey(floatingIp.id())) {
log.debug("The floating Ip is updated failed whose identifier is {}",
floatingIp.id().toString());
result = false;
}
}
}
}
}
return result;
}
@Override
public boolean removeFloatingIps(Collection<FloatingIpId> floatingIpIds) {
checkNotNull(floatingIpIds, FLOATINGIP_ID_NOT_NULL);
boolean result = true;
if (floatingIpIds != null) {
for (FloatingIpId floatingIpId : floatingIpIds) {
if (!floatingIpStore.containsKey(floatingIpId)) {
log.debug("The floatingIp is not exist whose identifier is {}",
floatingIpId.toString());
throw new IllegalArgumentException(
"FloatingIP ID doesn't exist");
}
FloatingIp floatingIp = floatingIpStore.get(floatingIpId);
floatingIpStore.remove(floatingIpId, floatingIp);
if (floatingIpStore.containsKey(floatingIpId)) {
log.debug("The floating Ip is deleted failed whose identifier is {}",
floatingIpId.toString());
result = false;
}
}
}
return result;
}
@Override
public void addListener(FloatingIpListener listener) {
checkNotNull(listener, LISTENER_NOT_NULL);
listeners.add(listener);
}
@Override
public void removeListener(FloatingIpListener listener) {
checkNotNull(listener, LISTENER_NOT_NULL);
listeners.add(listener);
}
/**
* Verifies validity of FloatingIp data.
*
* @param floatingIps floatingIp instance
*/
private void verifyFloatingIpData(FloatingIp floatingIps) {
checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
if (!tenantNetworkService.exists(floatingIps.networkId())) {
log.debug("The network identifier {} that the floating Ip {} create for is not exist",
floatingIps.networkId().toString(), floatingIps.id()
.toString());
throw new IllegalArgumentException(
"Floating network ID doesn't exist");
}
VirtualPortId portId = floatingIps.portId();
if (portId != null && !virtualPortService.exists(portId)) {
log.debug("The port identifier {} that the floating Ip {} create for is not exist",
floatingIps.portId().toString(), floatingIps.id()
.toString());
throw new IllegalArgumentException("Port ID doesn't exist");
}
RouterId routerId = floatingIps.routerId();
if (routerId != null && !routerService.exists(routerId)) {
log.debug("The router identifier {} that the floating Ip {} create for is not exist",
floatingIps.routerId().toString(), floatingIps.id()
.toString());
throw new IllegalArgumentException("Router ID doesn't exist");
}
if (floatingIpIsUsed(floatingIps.floatingIp(), floatingIps.id())) {
log.debug("The floaing Ip {} that the floating Ip {} create for is used",
floatingIps.floatingIp().toString(), floatingIps.id()
.toString());
throw new IllegalArgumentException(
"The floating IP address is used");
}
IpAddress fixedIp = floatingIps.fixedIp();
if (fixedIp != null
&& fixedIpIsUsed(fixedIp, floatingIps.tenantId(),
floatingIps.id())) {
log.debug("The fixed Ip {} that the floating Ip {} create for is used",
floatingIps.fixedIp().toString(), floatingIps.id()
.toString());
throw new IllegalArgumentException("The fixed IP address is used");
}
}
private class InnerFloatingIpStoreListener
implements
EventuallyConsistentMapListener<FloatingIpId, FloatingIp> {
@Override
public void event(EventuallyConsistentMapEvent<FloatingIpId, FloatingIp> event) {
checkNotNull(event, EVENT_NOT_NULL);
FloatingIp floatingIp = event.value();
if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
notifyListeners(new FloatingIpEvent(
FloatingIpEvent.Type.FLOATINGIP_PUT,
floatingIp));
}
if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
notifyListeners(new FloatingIpEvent(
FloatingIpEvent.Type.FLOATINGIP_DELETE,
floatingIp));
}
}
}
/**
* Notifies specify event to all listeners.
*
* @param event Floating IP event
*/
private void notifyListeners(FloatingIpEvent event) {
checkNotNull(event, EVENT_NOT_NULL);
listeners.forEach(listener -> listener.event(event));
}
}
/*
* 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.
*/
/**
* Provides implementation of the FloatingIp service.
*/
package org.onosproject.vtnrsc.floatingip.impl;
/*
* 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.vtnrsc.floatingip;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.vtnrsc.DefaultFloatingIp;
import org.onosproject.vtnrsc.FloatingIp;
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 com.google.common.testing.EqualsTester;
/**
* Unit tests for DefaultFloatingIp class.
*/
public class DefaultFloatingIpTest {
private String floatingIpIdStr1 = "5fb63824-4d5c-4b85-9f2f-ebb93c9ce3df";
private String floatingIpIdStr2 = "fa44f585-fe02-40d3-afe7-d1d7e5782c99";
private String floatingIpStr = "10.1.1.2";
private String fixedIpStr = "192.168.1.2";
private String tenantIdStr = "123";
private String tenantNetworkId = "1234567";
private String virtualPortId = "1212";
private String routerIdStr = "123";
/**
* Checks that the DefaultFloatingIp class is immutable.
*/
@Test
public void testImmutability() {
assertThatClassIsImmutable(DefaultFloatingIp.class);
}
/**
* Checks the operation of equals().
*/
@Test
public void testEquals() {
final TenantId tenantId = TenantId.tenantId(tenantIdStr);
final TenantNetworkId networkId = TenantNetworkId
.networkId(tenantNetworkId);
final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
final RouterId routerId = RouterId.valueOf(routerIdStr);
final FloatingIpId id1 = FloatingIpId.of(floatingIpIdStr1);
final FloatingIpId id2 = FloatingIpId.of(floatingIpIdStr2);
final IpAddress floatingIpAddress = IpAddress.valueOf(floatingIpStr);
final IpAddress fixedIpAddress = IpAddress.valueOf(fixedIpStr);
FloatingIp fip1 = new DefaultFloatingIp(id1, tenantId, networkId,
portId, routerId,
floatingIpAddress,
fixedIpAddress,
FloatingIp.Status.ACTIVE);
FloatingIp fip2 = new DefaultFloatingIp(id1, tenantId, networkId,
portId, routerId,
floatingIpAddress,
fixedIpAddress,
FloatingIp.Status.ACTIVE);
FloatingIp fip3 = new DefaultFloatingIp(id2, tenantId, networkId,
portId, routerId,
floatingIpAddress,
fixedIpAddress,
FloatingIp.Status.ACTIVE);
new EqualsTester().addEqualityGroup(fip1, fip2).addEqualityGroup(fip3)
.testEquals();
}
/**
* Checks the construction of a DefaultFloatingIp object.
*/
@Test
public void testConstruction() {
final TenantId tenantId = TenantId.tenantId(tenantIdStr);
final TenantNetworkId networkId = TenantNetworkId
.networkId(tenantNetworkId);
final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
final RouterId routerId = RouterId.valueOf(routerIdStr);
final FloatingIpId id = FloatingIpId.of(floatingIpIdStr1);
final IpAddress floatingIpAddress = IpAddress.valueOf(floatingIpStr);
final IpAddress fixedIpAddress = IpAddress.valueOf(fixedIpStr);
FloatingIp fip = new DefaultFloatingIp(id, tenantId, networkId, portId,
routerId, floatingIpAddress,
fixedIpAddress,
FloatingIp.Status.ACTIVE);
assertThat(id, is(notNullValue()));
assertThat(id, is(fip.id()));
assertThat(tenantId, is(notNullValue()));
assertThat(tenantId, is(fip.tenantId()));
assertThat(networkId, is(notNullValue()));
assertThat(networkId, is(fip.networkId()));
assertThat(portId, is(notNullValue()));
assertThat(portId, is(fip.portId()));
assertThat(routerId, is(notNullValue()));
assertThat(routerId, is(fip.routerId()));
assertThat(floatingIpAddress, is(notNullValue()));
assertThat(floatingIpAddress, is(fip.floatingIp()));
assertThat(fixedIpAddress, is(notNullValue()));
assertThat(fixedIpAddress, is(fip.fixedIp()));
}
}