Committed by
Gerrit Code Review
ONOS-1404 - Rerouting delayed due to flows being removed out of order
ONOS-1409 - handle all links to a switch going away and coming back Change-Id: Ib7216530fa8eef41b1088c5122a40bf9265481ca
Showing
8 changed files
with
93 additions
and
313 deletions
... | @@ -15,7 +15,15 @@ | ... | @@ -15,7 +15,15 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.net.intent.impl; | 16 | package org.onosproject.net.intent.impl; |
17 | 17 | ||
18 | -import com.google.common.collect.ImmutableList; | 18 | +import java.util.Collection; |
19 | +import java.util.EnumSet; | ||
20 | +import java.util.List; | ||
21 | +import java.util.Map; | ||
22 | +import java.util.concurrent.ExecutionException; | ||
23 | +import java.util.concurrent.ExecutorService; | ||
24 | +import java.util.concurrent.Future; | ||
25 | +import java.util.stream.Collectors; | ||
26 | + | ||
19 | import org.apache.felix.scr.annotations.Activate; | 27 | import org.apache.felix.scr.annotations.Activate; |
20 | import org.apache.felix.scr.annotations.Component; | 28 | import org.apache.felix.scr.annotations.Component; |
21 | import org.apache.felix.scr.annotations.Deactivate; | 29 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -48,15 +56,7 @@ import org.onosproject.net.intent.impl.phase.IntentProcessPhase; | ... | @@ -48,15 +56,7 @@ import org.onosproject.net.intent.impl.phase.IntentProcessPhase; |
48 | import org.onosproject.net.intent.impl.phase.IntentWorker; | 56 | import org.onosproject.net.intent.impl.phase.IntentWorker; |
49 | import org.slf4j.Logger; | 57 | import org.slf4j.Logger; |
50 | 58 | ||
51 | -import java.util.Collection; | 59 | +import com.google.common.collect.ImmutableList; |
52 | -import java.util.Collections; | ||
53 | -import java.util.EnumSet; | ||
54 | -import java.util.List; | ||
55 | -import java.util.Map; | ||
56 | -import java.util.concurrent.ExecutionException; | ||
57 | -import java.util.concurrent.ExecutorService; | ||
58 | -import java.util.concurrent.Future; | ||
59 | -import java.util.stream.Collectors; | ||
60 | 60 | ||
61 | import static com.google.common.base.Preconditions.checkNotNull; | 61 | import static com.google.common.base.Preconditions.checkNotNull; |
62 | import static java.util.concurrent.Executors.newFixedThreadPool; | 62 | import static java.util.concurrent.Executors.newFixedThreadPool; |
... | @@ -359,97 +359,92 @@ public class IntentManager | ... | @@ -359,97 +359,92 @@ public class IntentManager |
359 | } | 359 | } |
360 | 360 | ||
361 | @Override | 361 | @Override |
362 | - public void install(IntentData data) { | 362 | + public void apply(IntentData toUninstall, IntentData toInstall) { |
363 | - IntentManager.this.install(data); | 363 | + IntentManager.this.apply(toUninstall, toInstall); |
364 | } | 364 | } |
365 | - | ||
366 | - @Override | ||
367 | - public void uninstall(IntentData data) { | ||
368 | - IntentManager.this.uninstall(data); | ||
369 | - } | ||
370 | - | ||
371 | } | 365 | } |
372 | 366 | ||
373 | - private void install(IntentData data) { | 367 | + private enum Direction { |
374 | - // need to consider if FlowRuleIntent is only one as installable intent or not | 368 | + ADD, |
375 | - List<Intent> installables = data.installables(); | 369 | + REMOVE |
376 | - if (!installables.stream().allMatch(x -> x instanceof FlowRuleIntent)) { | 370 | + } |
377 | - throw new IllegalStateException("installable intents must be FlowRuleIntent"); | ||
378 | - } | ||
379 | 371 | ||
380 | - trackerService.addTrackedResources(data.key(), data.intent().resources()); | 372 | + private void applyIntentData(IntentData data, |
381 | - installables.forEach(installable -> | 373 | + FlowRuleOperations.Builder builder, |
382 | - trackerService.addTrackedResources(data.key(), installable.resources())); | 374 | + Direction direction) { |
375 | + if (data != null) { | ||
376 | + List<Intent> intentsToApply = data.installables(); | ||
377 | + if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) { | ||
378 | + throw new IllegalStateException("installable intents must be FlowRuleIntent"); | ||
379 | + } | ||
383 | 380 | ||
384 | - List<Collection<FlowRule>> stages = installables.stream() | 381 | + if (direction == Direction.ADD) { |
385 | - .map(x -> (FlowRuleIntent) x) | 382 | + trackerService.addTrackedResources(data.key(), data.intent().resources()); |
386 | - .map(FlowRuleIntent::flowRules) | 383 | + intentsToApply.forEach(installable -> |
387 | - .collect(Collectors.toList()); | 384 | + trackerService.addTrackedResources(data.key(), installable.resources())); |
385 | + } else { | ||
386 | + trackerService.removeTrackedResources(data.key(), data.intent().resources()); | ||
387 | + intentsToApply.forEach(installable -> | ||
388 | + trackerService.removeTrackedResources(data.intent().key(), | ||
389 | + installable.resources())); | ||
390 | + } | ||
388 | 391 | ||
389 | - FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); | 392 | + // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so. |
390 | - for (Collection<FlowRule> rules : stages) { | ||
391 | - rules.forEach(builder::add); | ||
392 | builder.newStage(); | 393 | builder.newStage(); |
393 | - } | ||
394 | 394 | ||
395 | - FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() { | 395 | + List<Collection<FlowRule>> stages = intentsToApply.stream() |
396 | - @Override | 396 | + .map(x -> (FlowRuleIntent) x) |
397 | - public void onSuccess(FlowRuleOperations ops) { | 397 | + .map(FlowRuleIntent::flowRules) |
398 | - log.debug("Completed installing: {}", data.key()); | 398 | + .collect(Collectors.toList()); |
399 | - data.setState(INSTALLED); | ||
400 | - store.write(data); | ||
401 | - } | ||
402 | 399 | ||
403 | - @Override | 400 | + for (Collection<FlowRule> rules : stages) { |
404 | - public void onError(FlowRuleOperations ops) { | 401 | + if (direction == Direction.ADD) { |
405 | - log.warn("Failed installation: {} {} on {}", data.key(), data.intent(), ops); | 402 | + rules.forEach(builder::add); |
406 | - data.setState(FAILED); | 403 | + } else { |
407 | - store.write(data); | 404 | + rules.forEach(builder::remove); |
405 | + } | ||
408 | } | 406 | } |
409 | - }); | ||
410 | - | ||
411 | - flowRuleService.apply(operations); | ||
412 | - } | ||
413 | - | ||
414 | - private void uninstall(IntentData data) { | ||
415 | - List<Intent> installables = data.installables(); | ||
416 | - if (!installables.stream().allMatch(x -> x instanceof FlowRuleIntent)) { | ||
417 | - throw new IllegalStateException("installable intents must be FlowRuleIntent"); | ||
418 | } | 407 | } |
419 | 408 | ||
420 | - trackerService.removeTrackedResources(data.key(), data.intent().resources()); | 409 | + } |
421 | - installables.forEach(installable -> | ||
422 | - trackerService.removeTrackedResources(data.intent().key(), | ||
423 | - installable.resources())); | ||
424 | 410 | ||
425 | - List<Collection<FlowRule>> stages = installables.stream() | 411 | + private void apply(IntentData toUninstall, IntentData toInstall) { |
426 | - .map(x -> (FlowRuleIntent) x) | 412 | + // need to consider if FlowRuleIntent is only one as installable intent or not |
427 | - .map(FlowRuleIntent::flowRules) | ||
428 | - .collect(Collectors.toList()); | ||
429 | 413 | ||
430 | FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); | 414 | FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); |
431 | - for (Collection<FlowRule> rules : stages) { | 415 | + applyIntentData(toUninstall, builder, Direction.REMOVE); |
432 | - rules.forEach(builder::remove); | 416 | + applyIntentData(toInstall, builder, Direction.ADD); |
433 | - builder.newStage(); | ||
434 | - } | ||
435 | 417 | ||
436 | FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() { | 418 | FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() { |
437 | @Override | 419 | @Override |
438 | public void onSuccess(FlowRuleOperations ops) { | 420 | public void onSuccess(FlowRuleOperations ops) { |
439 | - log.debug("Completed withdrawing: {}", data.key()); | 421 | + if (toInstall != null) { |
440 | - data.setState(WITHDRAWN); | 422 | + log.debug("Completed installing: {}", toInstall.key()); |
441 | - data.setInstallables(Collections.emptyList()); | 423 | + //FIXME state depends on install.... we might want to pass this in. |
442 | - store.write(data); | 424 | + toInstall.setState(INSTALLED); |
425 | + store.write(toInstall); | ||
426 | + } else if (toUninstall != null) { | ||
427 | + log.debug("Completed withdrawing: {}", toUninstall.key()); | ||
428 | + //FIXME state depends on install.... we might want to pass this in. | ||
429 | + toUninstall.setState(WITHDRAWN); | ||
430 | + store.write(toUninstall); | ||
431 | + } | ||
443 | } | 432 | } |
444 | 433 | ||
445 | @Override | 434 | @Override |
446 | public void onError(FlowRuleOperations ops) { | 435 | public void onError(FlowRuleOperations ops) { |
447 | - log.warn("Failed withdraw: {}", data.key()); | 436 | + if (toInstall != null) { |
448 | - data.setState(FAILED); | 437 | + log.warn("Failed installation: {} {} on {}", toInstall.key(), toInstall.intent(), ops); |
449 | - store.write(data); | 438 | + //FIXME |
439 | + toInstall.setState(FAILED); | ||
440 | + store.write(toInstall); | ||
441 | + } | ||
442 | + // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT) | ||
443 | + // if toUninstall was cause of error, then CORRUPT (another job will lean this up) | ||
450 | } | 444 | } |
451 | }); | 445 | }); |
452 | 446 | ||
453 | flowRuleService.apply(operations); | 447 | flowRuleService.apply(operations); |
454 | } | 448 | } |
449 | + | ||
455 | } | 450 | } | ... | ... |
... | @@ -38,16 +38,8 @@ public interface IntentProcessor { | ... | @@ -38,16 +38,8 @@ public interface IntentProcessor { |
38 | List<Intent> compile(Intent intent, List<Intent> previousInstallables); | 38 | List<Intent> compile(Intent intent, List<Intent> previousInstallables); |
39 | 39 | ||
40 | /** | 40 | /** |
41 | - * Installs an intent included in the specified intent data. | 41 | + * @param toUninstall Intent data describing flows to uninstall. May be null. |
42 | - * | 42 | + * @param toInstall Intent data describing flows to install. May be null. |
43 | - * @param data intent data containing an intent to be installed | ||
44 | - */ | ||
45 | - void install(IntentData data); | ||
46 | - | ||
47 | - /** | ||
48 | - * Uninstalls an intent included in the specified intent data. | ||
49 | - * | ||
50 | - * @param data intent data containing an intent to be uninstalled | ||
51 | */ | 43 | */ |
52 | - void uninstall(IntentData data); | 44 | + void apply(IntentData toUninstall, IntentData toInstall); |
53 | } | 45 | } | ... | ... |
... | @@ -50,7 +50,7 @@ final class Compiling implements IntentProcessPhase { | ... | @@ -50,7 +50,7 @@ final class Compiling implements IntentProcessPhase { |
50 | public Optional<IntentProcessPhase> execute() { | 50 | public Optional<IntentProcessPhase> execute() { |
51 | try { | 51 | try { |
52 | data.setInstallables(processor.compile(data.intent(), null)); | 52 | data.setInstallables(processor.compile(data.intent(), null)); |
53 | - return Optional.of(new Installing(processor, data)); | 53 | + return Optional.of(new Installing(processor, data, null)); |
54 | } catch (IntentException e) { | 54 | } catch (IntentException e) { |
55 | log.debug("Unable to compile intent {} due to: {}", data.intent(), e); | 55 | log.debug("Unable to compile intent {} due to: {}", data.intent(), e); |
56 | return Optional.of(new CompileFailed(data)); | 56 | return Optional.of(new CompileFailed(data)); | ... | ... |
... | @@ -28,6 +28,7 @@ class Installing extends FinalIntentProcessPhase { | ... | @@ -28,6 +28,7 @@ class Installing extends FinalIntentProcessPhase { |
28 | 28 | ||
29 | private final IntentProcessor processor; | 29 | private final IntentProcessor processor; |
30 | private final IntentData data; | 30 | private final IntentData data; |
31 | + private final IntentData stored; | ||
31 | 32 | ||
32 | /** | 33 | /** |
33 | * Create an installing phase. | 34 | * Create an installing phase. |
... | @@ -35,15 +36,16 @@ class Installing extends FinalIntentProcessPhase { | ... | @@ -35,15 +36,16 @@ class Installing extends FinalIntentProcessPhase { |
35 | * @param processor intent processor that does work for installing | 36 | * @param processor intent processor that does work for installing |
36 | * @param data intent data containing an intent to be installed | 37 | * @param data intent data containing an intent to be installed |
37 | */ | 38 | */ |
38 | - Installing(IntentProcessor processor, IntentData data) { | 39 | + Installing(IntentProcessor processor, IntentData data, IntentData stored) { |
39 | this.processor = checkNotNull(processor); | 40 | this.processor = checkNotNull(processor); |
40 | this.data = checkNotNull(data); | 41 | this.data = checkNotNull(data); |
41 | this.data.setState(INSTALLING); | 42 | this.data.setState(INSTALLING); |
43 | + this.stored = stored; | ||
42 | } | 44 | } |
43 | 45 | ||
44 | @Override | 46 | @Override |
45 | public void preExecute() { | 47 | public void preExecute() { |
46 | - processor.install(data); | 48 | + processor.apply(stored, data); |
47 | } | 49 | } |
48 | 50 | ||
49 | @Override | 51 | @Override | ... | ... |
... | @@ -17,7 +17,10 @@ package org.onosproject.net.intent.impl.phase; | ... | @@ -17,7 +17,10 @@ package org.onosproject.net.intent.impl.phase; |
17 | 17 | ||
18 | import org.onosproject.net.intent.Intent; | 18 | import org.onosproject.net.intent.Intent; |
19 | import org.onosproject.net.intent.IntentData; | 19 | import org.onosproject.net.intent.IntentData; |
20 | +import org.onosproject.net.intent.IntentException; | ||
20 | import org.onosproject.net.intent.impl.IntentProcessor; | 21 | import org.onosproject.net.intent.impl.IntentProcessor; |
22 | +import org.slf4j.Logger; | ||
23 | +import org.slf4j.LoggerFactory; | ||
21 | 24 | ||
22 | import java.util.List; | 25 | import java.util.List; |
23 | import java.util.Optional; | 26 | import java.util.Optional; |
... | @@ -29,6 +32,8 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -29,6 +32,8 @@ import static com.google.common.base.Preconditions.checkNotNull; |
29 | */ | 32 | */ |
30 | class Recompiling implements IntentProcessPhase { | 33 | class Recompiling implements IntentProcessPhase { |
31 | 34 | ||
35 | + private static final Logger log = LoggerFactory.getLogger(Recompiling.class); | ||
36 | + | ||
32 | private final IntentProcessor processor; | 37 | private final IntentProcessor processor; |
33 | private final IntentData data; | 38 | private final IntentData data; |
34 | private final IntentData stored; | 39 | private final IntentData stored; |
... | @@ -48,8 +53,14 @@ class Recompiling implements IntentProcessPhase { | ... | @@ -48,8 +53,14 @@ class Recompiling implements IntentProcessPhase { |
48 | 53 | ||
49 | @Override | 54 | @Override |
50 | public Optional<IntentProcessPhase> execute() { | 55 | public Optional<IntentProcessPhase> execute() { |
51 | - List<Intent> compiled = processor.compile(data.intent(), stored.installables()); | 56 | + try { |
52 | - data.setInstallables(compiled); | 57 | + List<Intent> compiled = processor.compile(data.intent(), stored.installables()); |
53 | - return Optional.of(new Replacing(processor, data, stored)); | 58 | + data.setInstallables(compiled); |
59 | + return Optional.of(new Installing(processor, data, stored)); | ||
60 | + } catch (IntentException e) { | ||
61 | + log.debug("Unable to recompile intent {} due to: {}", data.intent(), e); | ||
62 | + // FIXME we need to removed orphaned flows and deallocate resources | ||
63 | + return Optional.of(new CompileFailed(data)); | ||
64 | + } | ||
54 | } | 65 | } |
55 | } | 66 | } | ... | ... |
1 | -/* | ||
2 | - * Copyright 2015 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 | -package org.onosproject.net.intent.impl.phase; | ||
17 | - | ||
18 | -import org.onosproject.net.intent.IntentData; | ||
19 | -import org.onosproject.net.intent.IntentException; | ||
20 | -import org.onosproject.net.intent.impl.IntentProcessor; | ||
21 | -import org.slf4j.Logger; | ||
22 | -import org.slf4j.LoggerFactory; | ||
23 | - | ||
24 | -import java.util.Optional; | ||
25 | - | ||
26 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
27 | - | ||
28 | -/** | ||
29 | - * Represents a phase to replace an intent. | ||
30 | - */ | ||
31 | -final class Replacing implements IntentProcessPhase { | ||
32 | - | ||
33 | - private static final Logger log = LoggerFactory.getLogger(Replacing.class); | ||
34 | - | ||
35 | - private final IntentProcessor processor; | ||
36 | - private final IntentData data; | ||
37 | - private final IntentData stored; | ||
38 | - | ||
39 | - /** | ||
40 | - * Creates a replacing phase. | ||
41 | - * | ||
42 | - * @param processor intent processor that does work for replacing | ||
43 | - * @param data intent data containing an intent to be replaced | ||
44 | - * @param stored intent data stored in the store | ||
45 | - */ | ||
46 | - Replacing(IntentProcessor processor, IntentData data, IntentData stored) { | ||
47 | - this.processor = checkNotNull(processor); | ||
48 | - this.data = checkNotNull(data); | ||
49 | - this.stored = checkNotNull(stored); | ||
50 | - } | ||
51 | - | ||
52 | - @Override | ||
53 | - public Optional<IntentProcessPhase> execute() { | ||
54 | - try { | ||
55 | - processor.uninstall(stored); | ||
56 | - return Optional.of(new Installing(processor, data)); | ||
57 | - } catch (IntentException e) { | ||
58 | - log.warn("Unable to generate a FlowRuleOperations from intent {} due to:", data.intent().id(), e); | ||
59 | - return Optional.of(new ReplaceFailed(data)); | ||
60 | - } | ||
61 | - } | ||
62 | -} |
... | @@ -44,7 +44,7 @@ class Withdrawing extends FinalIntentProcessPhase { | ... | @@ -44,7 +44,7 @@ class Withdrawing extends FinalIntentProcessPhase { |
44 | 44 | ||
45 | @Override | 45 | @Override |
46 | protected void preExecute() { | 46 | protected void preExecute() { |
47 | - processor.uninstall(data); | 47 | + processor.apply(data, null); |
48 | } | 48 | } |
49 | 49 | ||
50 | @Override | 50 | @Override | ... | ... |
1 | -/* | ||
2 | - * Copyright 2015 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 | -package org.onosproject.net.intent.impl.phase; | ||
17 | - | ||
18 | -import org.junit.After; | ||
19 | -import org.junit.Before; | ||
20 | -import org.junit.Test; | ||
21 | -import org.onosproject.TestApplicationId; | ||
22 | -import org.onosproject.core.ApplicationId; | ||
23 | -import org.onosproject.core.IdGenerator; | ||
24 | -import org.onosproject.net.ConnectPoint; | ||
25 | -import org.onosproject.net.DefaultLink; | ||
26 | -import org.onosproject.net.DefaultPath; | ||
27 | -import org.onosproject.net.Link; | ||
28 | -import org.onosproject.net.Path; | ||
29 | -import org.onosproject.net.flow.DefaultTrafficSelector; | ||
30 | -import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
31 | -import org.onosproject.net.flow.TrafficSelector; | ||
32 | -import org.onosproject.net.flow.TrafficTreatment; | ||
33 | -import org.onosproject.net.intent.Intent; | ||
34 | -import org.onosproject.net.intent.IntentData; | ||
35 | -import org.onosproject.net.intent.MockIdGenerator; | ||
36 | -import org.onosproject.net.intent.PathIntent; | ||
37 | -import org.onosproject.net.intent.PointToPointIntent; | ||
38 | -import org.onosproject.net.intent.impl.IntentInstallationException; | ||
39 | -import org.onosproject.net.intent.impl.IntentProcessor; | ||
40 | -import org.onosproject.net.provider.ProviderId; | ||
41 | -import org.onosproject.store.Timestamp; | ||
42 | - | ||
43 | -import java.util.Arrays; | ||
44 | -import java.util.List; | ||
45 | -import java.util.Optional; | ||
46 | - | ||
47 | -import static org.easymock.EasyMock.createMock; | ||
48 | -import static org.easymock.EasyMock.expectLastCall; | ||
49 | -import static org.easymock.EasyMock.replay; | ||
50 | -import static org.easymock.EasyMock.verify; | ||
51 | -import static org.hamcrest.Matchers.instanceOf; | ||
52 | -import static org.hamcrest.Matchers.is; | ||
53 | -import static org.junit.Assert.assertThat; | ||
54 | -import static org.onosproject.net.DeviceId.deviceId; | ||
55 | -import static org.onosproject.net.Link.Type.DIRECT; | ||
56 | -import static org.onosproject.net.PortNumber.portNumber; | ||
57 | -import static org.onosproject.net.intent.IntentState.INSTALLED; | ||
58 | -import static org.onosproject.net.intent.IntentState.INSTALL_REQ; | ||
59 | - | ||
60 | -/** | ||
61 | - * Unit tests for InstallingCoordinating phase. | ||
62 | - */ | ||
63 | -public class ReplacingTest { | ||
64 | - | ||
65 | - private final ApplicationId appId = new TestApplicationId("test"); | ||
66 | - private final ProviderId pid = new ProviderId("of", "test"); | ||
67 | - private final TrafficSelector selector = DefaultTrafficSelector.emptySelector(); | ||
68 | - private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment(); | ||
69 | - private final ConnectPoint cp1 = new ConnectPoint(deviceId("1"), portNumber(1)); | ||
70 | - private final ConnectPoint cp2 = new ConnectPoint(deviceId("1"), portNumber(2)); | ||
71 | - private final ConnectPoint cp3 = new ConnectPoint(deviceId("2"), portNumber(1)); | ||
72 | - private final ConnectPoint cp4 = new ConnectPoint(deviceId("2"), portNumber(2)); | ||
73 | - | ||
74 | - private final List<Link> links = Arrays.asList(new DefaultLink(pid, cp2, cp4, DIRECT)); | ||
75 | - private final Path path = new DefaultPath(pid, links, 10); | ||
76 | - | ||
77 | - private PointToPointIntent input; | ||
78 | - private PathIntent compiled; | ||
79 | - | ||
80 | - private IdGenerator idGenerator; | ||
81 | - private IntentProcessor processor; | ||
82 | - private Timestamp version; | ||
83 | - | ||
84 | - @Before | ||
85 | - public void setUp() { | ||
86 | - processor = createMock(IntentProcessor.class); | ||
87 | - version = createMock(Timestamp.class); | ||
88 | - | ||
89 | - idGenerator = new MockIdGenerator(); | ||
90 | - | ||
91 | - Intent.bindIdGenerator(idGenerator); | ||
92 | - | ||
93 | - // Intent creation should be placed after binding an ID generator | ||
94 | - input = PointToPointIntent.builder() | ||
95 | - .appId(appId) | ||
96 | - .selector(selector) | ||
97 | - .treatment(treatment) | ||
98 | - .ingressPoint(cp1) | ||
99 | - .egressPoint(cp3) | ||
100 | - .build(); | ||
101 | - compiled = PathIntent.builder() | ||
102 | - .appId(appId) | ||
103 | - .selector(selector) | ||
104 | - .treatment(treatment) | ||
105 | - .path(path) | ||
106 | - .build(); | ||
107 | - } | ||
108 | - | ||
109 | - | ||
110 | - @After | ||
111 | - public void tearDown() { | ||
112 | - Intent.unbindIdGenerator(idGenerator); | ||
113 | - } | ||
114 | - | ||
115 | - /** | ||
116 | - * Tests a next phase when no exception occurs. | ||
117 | - */ | ||
118 | - @Test | ||
119 | - public void testMoveToNextPhaseWithoutError() { | ||
120 | - IntentData pending = new IntentData(input, INSTALL_REQ, version); | ||
121 | - pending.setInstallables(Arrays.asList(compiled)); | ||
122 | - | ||
123 | - IntentData current = new IntentData(input, INSTALLED, version); | ||
124 | - current.setInstallables(Arrays.asList(compiled)); | ||
125 | - | ||
126 | - processor.uninstall(current); | ||
127 | - replay(processor); | ||
128 | - | ||
129 | - Replacing sut = new Replacing(processor, pending, current); | ||
130 | - | ||
131 | - Optional<IntentProcessPhase> executed = sut.execute(); | ||
132 | - | ||
133 | - verify(processor); | ||
134 | - assertThat(executed.get(), is(instanceOf(Installing.class))); | ||
135 | - } | ||
136 | - | ||
137 | - /** | ||
138 | - * Tests a next phase when IntentInstallationException occurs. | ||
139 | - */ | ||
140 | - @Test | ||
141 | - public void testWhenIntentInstallExceptionOccurs() { | ||
142 | - IntentData pending = new IntentData(input, INSTALL_REQ, version); | ||
143 | - pending.setInstallables(Arrays.asList(compiled)); | ||
144 | - | ||
145 | - IntentData current = new IntentData(input, INSTALLED, version); | ||
146 | - | ||
147 | - processor.uninstall(current); | ||
148 | - expectLastCall().andThrow(new IntentInstallationException()); | ||
149 | - replay(processor); | ||
150 | - | ||
151 | - Replacing sut = new Replacing(processor, pending, current); | ||
152 | - | ||
153 | - Optional<IntentProcessPhase> executed = sut.execute(); | ||
154 | - | ||
155 | - verify(processor); | ||
156 | - assertThat(executed.get(), is(instanceOf(ReplaceFailed.class))); | ||
157 | - } | ||
158 | -} |
-
Please register or login to post a comment