Yi Tseng | c927a06 | 2017-05-02 15:02:37 -0700 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2017-present Open Networking Laboratory |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package org.onosproject.net.intent.impl.installer; |
| 18 | |
| 19 | import com.fasterxml.jackson.databind.JsonNode; |
| 20 | import com.google.common.collect.ImmutableList; |
| 21 | import com.google.common.collect.Lists; |
| 22 | import com.google.common.collect.Sets; |
| 23 | import org.junit.After; |
| 24 | import org.junit.AfterClass; |
| 25 | import org.junit.Before; |
| 26 | import org.junit.BeforeClass; |
| 27 | import org.junit.Test; |
| 28 | import org.onlab.junit.TestUtils; |
| 29 | import org.onlab.osgi.ServiceDirectory; |
| 30 | import org.onlab.osgi.TestServiceDirectory; |
| 31 | import org.onosproject.codec.CodecService; |
| 32 | import org.onosproject.codec.impl.CodecManager; |
| 33 | import org.onosproject.net.ConnectPoint; |
| 34 | import org.onosproject.net.FilteredConnectPoint; |
| 35 | import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointDescription; |
| 36 | import org.onosproject.net.behaviour.protection.TransportEndpointDescription; |
| 37 | import org.onosproject.net.config.BaseConfig; |
| 38 | import org.onosproject.net.config.Config; |
| 39 | import org.onosproject.net.config.NetworkConfigEvent; |
| 40 | import org.onosproject.net.config.NetworkConfigListener; |
| 41 | import org.onosproject.net.config.NetworkConfigService; |
| 42 | import org.onosproject.net.config.NetworkConfigServiceAdapter; |
| 43 | import org.onosproject.net.intent.Intent; |
| 44 | import org.onosproject.net.intent.IntentData; |
| 45 | import org.onosproject.net.intent.IntentInstallationContext; |
| 46 | import org.onosproject.net.intent.IntentOperationContext; |
| 47 | import org.onosproject.net.intent.IntentState; |
| 48 | import org.onosproject.net.intent.ProtectionEndpointIntent; |
| 49 | import org.onosproject.store.service.WallClockTimestamp; |
| 50 | |
| 51 | import java.util.List; |
| 52 | import java.util.Set; |
| 53 | import java.util.concurrent.CompletableFuture; |
| 54 | |
| 55 | import static org.junit.Assert.assertEquals; |
| 56 | |
| 57 | /** |
| 58 | * Tests for protection endpoint Intent installer. |
| 59 | */ |
| 60 | public class ProtectionEndpointIntentInstallerTest extends AbstractIntentInstallerTest { |
| 61 | private static final String FINGERPRINT = "Test fingerprint"; |
| 62 | protected ProtectionEndpointIntentInstaller installer; |
| 63 | protected NetworkConfigService networkConfigService; |
| 64 | private static TestServiceDirectory directory; |
| 65 | private static ServiceDirectory original; |
| 66 | |
| 67 | @BeforeClass |
| 68 | public static void setUpClass() throws TestUtils.TestUtilsException { |
| 69 | directory = new TestServiceDirectory(); |
| 70 | |
| 71 | CodecManager codecService = new CodecManager(); |
| 72 | codecService.activate(); |
| 73 | directory.add(CodecService.class, codecService); |
| 74 | |
| 75 | // replace service directory used by BaseConfig |
| 76 | original = TestUtils.getField(BaseConfig.class, "services"); |
| 77 | TestUtils.setField(BaseConfig.class, "services", directory); |
| 78 | } |
| 79 | |
| 80 | @AfterClass |
| 81 | public static void tearDownClass() throws TestUtils.TestUtilsException { |
| 82 | TestUtils.setField(BaseConfig.class, "services", original); |
| 83 | } |
| 84 | |
| 85 | @Before |
| 86 | public void setup() { |
| 87 | super.setup(); |
| 88 | networkConfigService = new TestNetworkConfigService(); |
| 89 | installer = new ProtectionEndpointIntentInstaller(); |
| 90 | installer.networkConfigService = networkConfigService; |
| 91 | installer.intentExtensionService = intentExtensionService; |
| 92 | installer.intentInstallCoordinator = intentInstallCoordinator; |
| 93 | installer.trackerService = trackerService; |
| 94 | |
| 95 | installer.activate(); |
| 96 | } |
| 97 | |
| 98 | @After |
| 99 | public void tearDown() { |
| 100 | super.tearDown(); |
| 101 | installer.deactivated(); |
| 102 | } |
| 103 | |
| 104 | /** |
| 105 | * Installs protection endpoint Intents. |
| 106 | * framework. |
| 107 | */ |
| 108 | @Test |
| 109 | public void testInstallIntents() { |
| 110 | List<Intent> intentsToUninstall = Lists.newArrayList(); |
| 111 | List<Intent> intentsToInstall = createProtectionIntents(CP2); |
| 112 | IntentData toUninstall = null; |
| 113 | IntentData toInstall = new IntentData(createP2PIntent(), |
| 114 | IntentState.INSTALLING, |
| 115 | new WallClockTimestamp()); |
| 116 | toInstall = new IntentData(toInstall, intentsToInstall); |
| 117 | IntentOperationContext<ProtectionEndpointIntent> operationContext; |
| 118 | IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall); |
| 119 | operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context); |
| 120 | installer.apply(operationContext); |
| 121 | assertEquals(intentInstallCoordinator.successContext, operationContext); |
| 122 | } |
| 123 | |
| 124 | /** |
| 125 | * Uninstalls protection endpoint Intents. |
| 126 | * framework. |
| 127 | */ |
| 128 | @Test |
| 129 | public void testUninstallIntents() { |
| 130 | List<Intent> intentsToUninstall = createProtectionIntents(CP2); |
| 131 | List<Intent> intentsToInstall = Lists.newArrayList(); |
| 132 | IntentData toUninstall = new IntentData(createP2PIntent(), |
| 133 | IntentState.INSTALLING, |
| 134 | new WallClockTimestamp()); |
| 135 | IntentData toInstall = null; |
| 136 | IntentOperationContext<ProtectionEndpointIntent> operationContext; |
| 137 | IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall); |
| 138 | operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context); |
| 139 | installer.apply(operationContext); |
| 140 | assertEquals(intentInstallCoordinator.successContext, operationContext); |
| 141 | } |
| 142 | |
| 143 | /** |
| 144 | * Test both uninstall and install protection endpoint Intents. |
| 145 | * framework. |
| 146 | */ |
| 147 | @Test |
| 148 | public void testUninstallAndInstallIntents() { |
| 149 | List<Intent> intentsToUninstall = createProtectionIntents(CP2); |
| 150 | List<Intent> intentsToInstall = createProtectionIntents(CP3); |
| 151 | IntentData toUninstall = new IntentData(createP2PIntent(), |
| 152 | IntentState.INSTALLED, |
| 153 | new WallClockTimestamp()); |
| 154 | toUninstall = new IntentData(toUninstall, intentsToInstall); |
| 155 | IntentData toInstall = new IntentData(createP2PIntent(), |
| 156 | IntentState.INSTALLING, |
| 157 | new WallClockTimestamp()); |
| 158 | toInstall = new IntentData(toInstall, intentsToInstall); |
| 159 | IntentOperationContext<ProtectionEndpointIntent> operationContext; |
| 160 | IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall); |
| 161 | operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context); |
| 162 | installer.apply(operationContext); |
| 163 | assertEquals(intentInstallCoordinator.successContext, operationContext); |
| 164 | } |
| 165 | |
| 166 | /** |
| 167 | * Nothing to uninstall or install. |
| 168 | */ |
| 169 | @Test |
| 170 | public void testNoAnyIntentToApply() { |
| 171 | IntentData toInstall = null; |
| 172 | IntentData toUninstall = null; |
| 173 | IntentOperationContext<ProtectionEndpointIntent> operationContext; |
| 174 | IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall); |
| 175 | operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context); |
| 176 | installer.apply(operationContext); |
| 177 | IntentOperationContext successContext = intentInstallCoordinator.successContext; |
| 178 | assertEquals(successContext, operationContext); |
| 179 | } |
| 180 | |
| 181 | /** |
| 182 | * Test if installation failed. |
| 183 | * framework. |
| 184 | */ |
| 185 | @Test |
| 186 | public void testInstallFailed() { |
| 187 | networkConfigService = new TestFailedNetworkConfigService(); |
| 188 | installer.networkConfigService = networkConfigService; |
| 189 | List<Intent> intentsToUninstall = Lists.newArrayList(); |
| 190 | List<Intent> intentsToInstall = createProtectionIntents(CP2); |
| 191 | IntentData toUninstall = null; |
| 192 | IntentData toInstall = new IntentData(createP2PIntent(), |
| 193 | IntentState.INSTALLING, |
| 194 | new WallClockTimestamp()); |
| 195 | toInstall = new IntentData(toInstall, intentsToInstall); |
| 196 | IntentOperationContext<ProtectionEndpointIntent> operationContext; |
| 197 | IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall); |
| 198 | operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context); |
| 199 | installer.apply(operationContext); |
| 200 | assertEquals(intentInstallCoordinator.failedContext, operationContext); |
| 201 | } |
| 202 | |
| 203 | /** |
| 204 | * Creates protection endpoint Intents by givent output point. |
| 205 | * |
| 206 | * @param output the output point |
| 207 | * @return the protection endpoint Intents |
| 208 | */ |
| 209 | private List<Intent> createProtectionIntents(ConnectPoint output) { |
| 210 | FilteredConnectPoint filteredOutput = new FilteredConnectPoint(output); |
| 211 | TransportEndpointDescription path = TransportEndpointDescription.builder() |
| 212 | .withOutput(filteredOutput) |
| 213 | .withEnabled(true).build(); |
| 214 | |
| 215 | List<TransportEndpointDescription> paths = ImmutableList.of(path); |
| 216 | ProtectedTransportEndpointDescription description = |
| 217 | ProtectedTransportEndpointDescription.of(paths, CP2.deviceId(), FINGERPRINT); |
| 218 | ProtectionEndpointIntent intent = ProtectionEndpointIntent.builder() |
| 219 | .appId(APP_ID) |
| 220 | .description(description) |
| 221 | .deviceId(CP1.deviceId()) |
| 222 | .key(KEY1) |
| 223 | .resourceGroup(RG1) |
| 224 | .build(); |
| 225 | |
| 226 | return ImmutableList.of(intent); |
| 227 | } |
| 228 | |
| 229 | class TestNetworkConfigService extends NetworkConfigServiceAdapter { |
| 230 | protected Set<NetworkConfigListener> listeners = Sets.newHashSet(); |
| 231 | |
| 232 | @Override |
| 233 | public void addListener(NetworkConfigListener listener) { |
| 234 | listeners.add(listener); |
| 235 | } |
| 236 | |
| 237 | @Override |
| 238 | public void removeListener(NetworkConfigListener listener) { |
| 239 | listeners.remove(listener); |
| 240 | } |
| 241 | |
| 242 | @Override |
| 243 | public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) { |
| 244 | NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED, |
| 245 | subject, |
| 246 | configClass); |
| 247 | CompletableFuture.runAsync(() -> { |
| 248 | listeners.forEach(listener -> listener.event(event)); |
| 249 | }); |
| 250 | return null; |
| 251 | } |
| 252 | |
| 253 | @Override |
| 254 | public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) { |
| 255 | NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_REMOVED, |
| 256 | subject, |
| 257 | configClass); |
| 258 | CompletableFuture.runAsync(() -> { |
| 259 | listeners.forEach(listener -> listener.event(event)); |
| 260 | }); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | /** |
| 265 | * Test network config service; will send wrong events to listeners. |
| 266 | */ |
| 267 | class TestFailedNetworkConfigService extends TestNetworkConfigService { |
| 268 | |
| 269 | @Override |
| 270 | public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) { |
| 271 | NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_REMOVED, |
| 272 | subject, |
| 273 | configClass); |
| 274 | CompletableFuture.runAsync(() -> { |
| 275 | listeners.forEach(listener -> listener.event(event)); |
| 276 | }); |
| 277 | return null; |
| 278 | } |
| 279 | |
| 280 | @Override |
| 281 | public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) { |
| 282 | NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED, |
| 283 | subject, |
| 284 | configClass); |
| 285 | CompletableFuture.runAsync(() -> { |
| 286 | listeners.forEach(listener -> listener.event(event)); |
| 287 | }); |
| 288 | } |
| 289 | } |
| 290 | } |