Brian Stanke

ONOS-2184 - Removing obsolete PtToPtIntentVirtualNetworkProvider.

Change-Id: Ib1266e0088fea60f403cb6c90c3dca4c084a4afe
/*
* Copyright 2016-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.incubator.net.virtual.impl;
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.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
import org.onosproject.net.provider.AbstractProvider;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Point to point intent VirtualNetworkProvider implementation.
*/
@Component(immediate = true)
@Service
public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider
implements VirtualNetworkProvider {
private final Logger log = getLogger(PtToPtIntentVirtualNetworkProvider.class);
private static final String NETWORK_ID_NULL = "Network ID cannot be null";
private static final String CONNECT_POINT_NULL = "Connect Point cannot be null";
private static final String INTENT_NULL = "Intent cannot be null";
private static final String NETWORK_ID = "networkId=";
protected static final String KEY_FORMAT = NETWORK_ID + "%s, src=%s, dst=%s";
private static final int MAX_WAIT_COUNT = 30;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected VirtualNetworkProviderRegistry providerRegistry;
private VirtualNetworkProviderService providerService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
private final InternalPtPtIntentListener intentListener = new InternalPtPtIntentListener();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
protected static final String PTPT_INTENT_APPID = "org.onosproject.vnet.intent";
private ApplicationId appId;
/**
* Default constructor.
*/
public PtToPtIntentVirtualNetworkProvider() {
super(DefaultVirtualLink.PID);
}
@Activate
public void activate() {
providerService = providerRegistry.register(this);
appId = coreService.registerApplication(PTPT_INTENT_APPID);
intentService.addListener(intentListener);
log.info("Started");
}
@Deactivate
public void deactivate() {
intentService.removeListener(intentListener);
providerRegistry.unregister(this);
providerService = null;
log.info("Stopped");
}
@Override
public boolean isTraversable(ConnectPoint src, ConnectPoint dst) {
return false;
}
@Override
public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
checkNotNull(networkId, NETWORK_ID_NULL);
checkNotNull(src, CONNECT_POINT_NULL);
checkNotNull(dst, CONNECT_POINT_NULL);
Key intentKey = encodeKey(networkId, src, dst);
List<Constraint> constraints = new ArrayList<>();
constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
// TODO Currently there can only be one tunnel/intent between the src and dst across
// all virtual networks. We may want to support multiple intents between the same src/dst pairs.
PointToPointIntent intent = PointToPointIntent.builder()
.key(intentKey)
.appId(appId)
.ingressPoint(src)
.egressPoint(dst)
.constraints(constraints)
.build();
intentService.submit(intent);
// construct tunnelId from the key
return TunnelId.valueOf(intentKey.toString());
}
@Override
public void destroyTunnel(NetworkId networkId, TunnelId tunnelId) {
String key = tunnelId.id();
Key intentKey = Key.of(key, appId);
Intent intent = intentService.getIntent(intentKey);
checkNotNull(intent, INTENT_NULL);
intentService.withdraw(intent);
}
private NetworkId decodeNetworkIdFromKey(Key intentKey) {
// Extract the network identifier from the intent key
StringTokenizer tokenizer = new StringTokenizer(intentKey.toString(), ",");
String networkIdString = tokenizer.nextToken().substring(NETWORK_ID.length());
return NetworkId.networkId(Integer.valueOf(networkIdString));
}
private Key encodeKey(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
String key = String.format(KEY_FORMAT, networkId, src, dst);
return Key.of(key, appId);
}
private class InternalPtPtIntentListener implements IntentListener {
@Override
public void event(IntentEvent event) {
PointToPointIntent intent = (PointToPointIntent) event.subject();
Key intentKey = intent.key();
// Ignore intent events that are not relevant.
if (!isRelevant(event)) {
return;
}
NetworkId networkId = decodeNetworkIdFromKey(intentKey);
ConnectPoint src = intent.ingressPoint();
ConnectPoint dst = intent.egressPoint();
switch (event.type()) {
case INSTALLED:
providerService.tunnelUp(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
break;
case WITHDRAWN:
intentService.purge(intent);
// Fall through and notify the provider service that the tunnel is down
// for both WITHDRAWN and FAILED intent event types.
case FAILED:
providerService.tunnelDown(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
break;
case INSTALL_REQ:
case CORRUPT:
case PURGED:
break; // Not sure what do with these events, ignore for now.
default:
break;
}
}
@Override
public boolean isRelevant(IntentEvent event) {
if (event.subject() instanceof PointToPointIntent) {
PointToPointIntent intent = (PointToPointIntent) event.subject();
// Only events that are for this appId are relevent.
return intent.appId().equals(appId);
}
return false;
}
}
}
/*
* Copyright 2016-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.incubator.net.virtual.impl;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.IdGenerator;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.FakeIntentManager;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentTestsMocks;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.TestableIntentService;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
/**
* Junit tests for PtToPtIntentVirtualNetworkProvider.
*/
public class PtToPtIntentVirtualNetworkProviderTest {
private PtToPtIntentVirtualNetworkProvider provider;
private VirtualNetworkProviderRegistry providerRegistry;
private final VirtualNetworkRegistryAdapter virtualNetworkRegistry = new VirtualNetworkRegistryAdapter();
private TestableIntentService intentService = new FakeIntentManager();
private TestListener listener = new TestListener();
protected TestIntentCompiler compiler = new TestIntentCompiler();
private IntentExtensionService intentExtensionService;
private static final ApplicationId APP_ID =
TestApplicationId.create(PtToPtIntentVirtualNetworkProvider.PTPT_INTENT_APPID);
private IdGenerator idGenerator = new MockIdGenerator();
private static final int MAX_WAIT_TIME = 5;
private static final int MAX_PERMITS = 2;
private static Semaphore created;
private static Semaphore removed;
@Before
public void setUp() {
provider = new PtToPtIntentVirtualNetworkProvider();
provider.providerRegistry = virtualNetworkRegistry;
final CoreService mockCoreService = createMock(CoreService.class);
provider.coreService = mockCoreService;
expect(mockCoreService.registerApplication(PtToPtIntentVirtualNetworkProvider.PTPT_INTENT_APPID))
.andReturn(APP_ID).anyTimes();
replay(mockCoreService);
Intent.unbindIdGenerator(idGenerator);
Intent.bindIdGenerator(idGenerator);
intentService.addListener(listener);
provider.intentService = intentService;
// Register a compiler and an installer both setup for success.
intentExtensionService = intentService;
intentExtensionService.registerCompiler(PointToPointIntent.class, compiler);
provider.activate();
created = new Semaphore(0, true);
removed = new Semaphore(0, true);
}
@After
public void tearDown() {
Intent.unbindIdGenerator(idGenerator);
intentService.removeListener(listener);
provider.deactivate();
provider.providerRegistry = null;
provider.coreService = null;
provider.intentService = null;
created = null;
removed = null;
}
@Test
public void basics() {
assertNotNull("registration expected", provider);
}
/**
* Test a null network identifier.
*/
@Test(expected = NullPointerException.class)
public void testCreateTunnelNullNetworkId() {
provider.createTunnel(null, null, null);
}
/**
* Test a null source connect point.
*/
@Test(expected = NullPointerException.class)
public void testCreateTunnelNullSrc() {
ConnectPoint dst = new ConnectPoint(DeviceId.deviceId("device2"), PortNumber.portNumber(2));
provider.createTunnel(NetworkId.networkId(0), null, dst);
}
/**
* Test a null destination connect point.
*/
@Test(expected = NullPointerException.class)
public void testCreateTunnelNullDst() {
ConnectPoint src = new ConnectPoint(DeviceId.deviceId("device1"), PortNumber.portNumber(1));
provider.createTunnel(NetworkId.networkId(0), src, null);
}
/**
* Test creating/destroying a valid tunnel.
*/
@Test
public void testCreateRemoveTunnel() {
NetworkId networkId = NetworkId.networkId(0);
ConnectPoint src = new ConnectPoint(DeviceId.deviceId("device1"), PortNumber.portNumber(1));
ConnectPoint dst = new ConnectPoint(DeviceId.deviceId("device2"), PortNumber.portNumber(2));
TunnelId tunnelId = provider.createTunnel(networkId, src, dst);
// Wait for the tunnel to go into an INSTALLED state, and that the tunnelUp method was called.
try {
if (!created.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
fail("Failed to wait for tunnel to get installed.");
}
} catch (InterruptedException e) {
fail("Semaphore exception during tunnel installation." + e.getMessage());
}
String key = String.format(PtToPtIntentVirtualNetworkProvider.KEY_FORMAT,
networkId.toString(), src.toString(), dst.toString());
assertEquals("TunnelId does not match as expected.", key, tunnelId.toString());
provider.destroyTunnel(networkId, tunnelId);
// Wait for the tunnel to go into a WITHDRAWN state, and that the tunnelDown method was called.
try {
if (!removed.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
fail("Failed to wait for tunnel to get removed.");
}
} catch (InterruptedException e) {
fail("Semaphore exception during tunnel removal." + e.getMessage());
}
}
/**
* Virtual network registry implementation for this test class.
*/
private class VirtualNetworkRegistryAdapter implements VirtualNetworkProviderRegistry {
private VirtualNetworkProvider provider;
@Override
public VirtualNetworkProviderService register(VirtualNetworkProvider theProvider) {
this.provider = theProvider;
return new TestVirtualNetworkProviderService(theProvider);
}
@Override
public void unregister(VirtualNetworkProvider theProvider) {
this.provider = null;
}
@Override
public Set<ProviderId> getProviders() {
return null;
}
}
/**
* Virtual network provider service implementation for this test class.
*/
private class TestVirtualNetworkProviderService
extends AbstractProviderService<VirtualNetworkProvider>
implements VirtualNetworkProviderService {
protected TestVirtualNetworkProviderService(VirtualNetworkProvider provider) {
super(provider);
}
@Override
public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
}
@Override
public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
// Release one permit on the created semaphore since the tunnelUp method was called.
created.release();
}
@Override
public void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
// Release one permit on the removed semaphore since the tunnelDown method was called.
removed.release();
}
}
private static class TestListener implements IntentListener {
@Override
public void event(IntentEvent event) {
switch (event.type()) {
case INSTALLED:
// Release one permit on the created semaphore since the Intent event was received.
created.release();
break;
case WITHDRAWN:
// Release one permit on the removed semaphore since the Intent event was received.
removed.release();
break;
default:
break;
}
}
}
/**
* Core service test class.
*/
private class TestCoreService extends CoreServiceAdapter {
@Override
public IdGenerator getIdGenerator(String topic) {
return new IdGenerator() {
private AtomicLong counter = new AtomicLong(0);
@Override
public long getNewId() {
return counter.getAndIncrement();
}
};
}
}
private static class TestIntentCompiler implements IntentCompiler<PointToPointIntent> {
@Override
public List<Intent> compile(PointToPointIntent intent, List<Intent> installable) {
return Lists.newArrayList(new MockInstallableIntent());
}
}
private static class MockInstallableIntent extends FlowRuleIntent {
public MockInstallableIntent() {
super(APP_ID, Collections.singletonList(new IntentTestsMocks.MockFlowRule(100)), Collections.emptyList());
}
}
}
......@@ -81,7 +81,7 @@ public class VirtualNetworkIntentServiceTest extends TestDeviceParams {
private final String tenantIdValue1 = "TENANT_ID1";
private static final ApplicationId APP_ID =
new TestApplicationId(PtToPtIntentVirtualNetworkProvider.PTPT_INTENT_APPID);
new TestApplicationId("MyAppId");
private ConnectPoint cp1;
private ConnectPoint cp2;
......