Committed by
Gerrit Code Review
Initial work for adding flow-objective backed intents.
Split installation work from IntentManager into IntentInstaller helper class. Change-Id: If926ce975d005abee4f22f2b05404de328d94203
Showing
5 changed files
with
397 additions
and
127 deletions
1 | +/* | ||
2 | + * Copyright 2016 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; | ||
18 | + | ||
19 | +import com.google.common.base.MoreObjects; | ||
20 | +import org.onosproject.core.ApplicationId; | ||
21 | +import org.onosproject.net.NetworkResource; | ||
22 | +import org.onosproject.net.flowobjective.Objective; | ||
23 | + | ||
24 | +import java.util.Collection; | ||
25 | + | ||
26 | +/** | ||
27 | + * Intent expressed as (and backed by) a collection of flow objectives through | ||
28 | + * which the intent is to be accomplished. | ||
29 | + */ | ||
30 | +public class FlowObjectiveIntent extends Intent { | ||
31 | + | ||
32 | + private final Collection<Objective> objectives; | ||
33 | + | ||
34 | + /** | ||
35 | + * Constructor for serialization. | ||
36 | + */ | ||
37 | + protected FlowObjectiveIntent() { | ||
38 | + super(); | ||
39 | + this.objectives = null; | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * Creates a flow objective intent with the specified objectives and | ||
44 | + * resources. | ||
45 | + * | ||
46 | + * @param appId application id | ||
47 | + * @param objectives backing flow objectives | ||
48 | + * @param resources backing network resources | ||
49 | + */ | ||
50 | + public FlowObjectiveIntent(ApplicationId appId, | ||
51 | + Collection<Objective> objectives, | ||
52 | + Collection<NetworkResource> resources) { | ||
53 | + this(appId, null, objectives, resources); | ||
54 | + } | ||
55 | + | ||
56 | + /** | ||
57 | + * Creates a flow objective intent with the specified objectives and | ||
58 | + * resources. | ||
59 | + * | ||
60 | + * @param appId application id | ||
61 | + * @param key intent key | ||
62 | + * @param objectives backing flow objectives | ||
63 | + * @param resources backing network resources | ||
64 | + */ | ||
65 | + public FlowObjectiveIntent(ApplicationId appId, Key key, | ||
66 | + Collection<Objective> objectives, | ||
67 | + Collection<NetworkResource> resources) { | ||
68 | + super(appId, key, resources, DEFAULT_INTENT_PRIORITY); | ||
69 | + this.objectives = objectives; | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * Returns the collection of backing flow objectives. | ||
74 | + * | ||
75 | + * @return flow objectives | ||
76 | + */ | ||
77 | + Collection<Objective> objectives() { | ||
78 | + return objectives; | ||
79 | + } | ||
80 | + | ||
81 | + | ||
82 | + @Override | ||
83 | + public boolean isInstallable() { | ||
84 | + return true; | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public String toString() { | ||
89 | + return MoreObjects.toStringHelper(this) | ||
90 | + .add("id", id()) | ||
91 | + .add("key", key()) | ||
92 | + .add("appId", appId()) | ||
93 | + .add("resources", resources()) | ||
94 | + .add("objectives", objectives) | ||
95 | + .toString(); | ||
96 | + } | ||
97 | +} |
... | @@ -25,6 +25,7 @@ public abstract class AbstractIntentTest { | ... | @@ -25,6 +25,7 @@ public abstract class AbstractIntentTest { |
25 | 25 | ||
26 | @Before | 26 | @Before |
27 | public void setUp() throws Exception { | 27 | public void setUp() throws Exception { |
28 | + Intent.unbindIdGenerator(idGenerator); | ||
28 | Intent.bindIdGenerator(idGenerator); | 29 | Intent.bindIdGenerator(idGenerator); |
29 | } | 30 | } |
30 | 31 | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 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; | ||
18 | + | ||
19 | +import com.google.common.collect.ImmutableSet; | ||
20 | +import com.google.common.testing.EqualsTester; | ||
21 | +import org.junit.Test; | ||
22 | +import org.onosproject.core.ApplicationId; | ||
23 | +import org.onosproject.core.DefaultApplicationId; | ||
24 | +import org.onosproject.net.NetworkResource; | ||
25 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
26 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
27 | +import org.onosproject.net.flow.criteria.Criteria; | ||
28 | +import org.onosproject.net.flowobjective.DefaultFilteringObjective; | ||
29 | +import org.onosproject.net.flowobjective.DefaultForwardingObjective; | ||
30 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
31 | +import org.onosproject.net.flowobjective.Objective; | ||
32 | + | ||
33 | +import java.util.Collection; | ||
34 | + | ||
35 | +import static org.junit.Assert.assertEquals; | ||
36 | +import static org.junit.Assert.assertTrue; | ||
37 | +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; | ||
38 | + | ||
39 | +/** | ||
40 | + * Tests of the flow objective intent. | ||
41 | + */ | ||
42 | +public class FlowObjectiveIntentTest extends IntentTest { | ||
43 | + | ||
44 | + private static final ApplicationId APP_ID = new DefaultApplicationId(1, "foo"); | ||
45 | + private static final Key KEY = Key.of("bar", APP_ID); | ||
46 | + | ||
47 | + private static final Objective FO1 = DefaultFilteringObjective.builder() | ||
48 | + .fromApp(APP_ID).addCondition(Criteria.matchEthType(123)) | ||
49 | + .permit().add(); | ||
50 | + private static final Objective FO2 = DefaultForwardingObjective.builder() | ||
51 | + .fromApp(APP_ID) | ||
52 | + .withSelector(DefaultTrafficSelector.builder().matchEthType((short) 123).build()) | ||
53 | + .withTreatment(DefaultTrafficTreatment.emptyTreatment()) | ||
54 | + .withFlag(ForwardingObjective.Flag.VERSATILE).add(); | ||
55 | + private static final Collection<Objective> OBJECTIVES = ImmutableSet.of(FO1, FO2); | ||
56 | + private static final Collection<NetworkResource> RESOURCES = ImmutableSet.of(); | ||
57 | + | ||
58 | + /** | ||
59 | + * Tests basics of construction and getters. | ||
60 | + */ | ||
61 | + @Test | ||
62 | + public void basics() { | ||
63 | + FlowObjectiveIntent intent = | ||
64 | + new FlowObjectiveIntent(APP_ID, KEY, OBJECTIVES, RESOURCES); | ||
65 | + assertEquals("incorrect app id", APP_ID, intent.appId()); | ||
66 | + assertEquals("incorrect key", KEY, intent.key()); | ||
67 | + assertEquals("incorrect objectives", OBJECTIVES, intent.objectives()); | ||
68 | + assertEquals("incorrect resources", RESOURCES, intent.resources()); | ||
69 | + assertTrue("should be installable", intent.isInstallable()); | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * Tests equality. | ||
74 | + */ | ||
75 | + @Test | ||
76 | + public void equality() { | ||
77 | + Intent a = createOne(); | ||
78 | + Intent b = createAnother(); | ||
79 | + new EqualsTester().addEqualityGroup(a).addEqualityGroup(b).testEquals(); | ||
80 | + } | ||
81 | + | ||
82 | + /** | ||
83 | + * Tests that instance is immutable. | ||
84 | + */ | ||
85 | + @Test | ||
86 | + public void testImmutability() { | ||
87 | + assertThatClassIsImmutable(HostToHostIntent.class); | ||
88 | + } | ||
89 | + | ||
90 | + @Override | ||
91 | + protected Intent createOne() { | ||
92 | + return new FlowObjectiveIntent(APP_ID, OBJECTIVES, RESOURCES); | ||
93 | + } | ||
94 | + | ||
95 | + @Override | ||
96 | + protected Intent createAnother() { | ||
97 | + return new FlowObjectiveIntent(APP_ID, OBJECTIVES, RESOURCES); | ||
98 | + } | ||
99 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2016 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; | ||
18 | + | ||
19 | +import org.onosproject.net.flow.FlowRule; | ||
20 | +import org.onosproject.net.flow.FlowRuleOperations; | ||
21 | +import org.onosproject.net.flow.FlowRuleOperationsContext; | ||
22 | +import org.onosproject.net.flow.FlowRuleService; | ||
23 | +import org.onosproject.net.flowobjective.FlowObjectiveService; | ||
24 | +import org.onosproject.net.intent.FlowRuleIntent; | ||
25 | +import org.onosproject.net.intent.Intent; | ||
26 | +import org.onosproject.net.intent.IntentData; | ||
27 | +import org.onosproject.net.intent.IntentStore; | ||
28 | +import org.slf4j.Logger; | ||
29 | + | ||
30 | +import java.util.Collection; | ||
31 | +import java.util.List; | ||
32 | +import java.util.Optional; | ||
33 | +import java.util.Set; | ||
34 | +import java.util.stream.Collectors; | ||
35 | + | ||
36 | +import static org.onosproject.net.intent.IntentState.*; | ||
37 | +import static org.slf4j.LoggerFactory.getLogger; | ||
38 | + | ||
39 | +/** | ||
40 | + * Auxiliary entity responsible for installing the intents into the environment. | ||
41 | + */ | ||
42 | +class IntentInstaller { | ||
43 | + | ||
44 | + private static final Logger log = getLogger(IntentManager.class); | ||
45 | + | ||
46 | + private IntentStore store; | ||
47 | + private ObjectiveTrackerService trackerService; | ||
48 | + private FlowRuleService flowRuleService; | ||
49 | + private FlowObjectiveService flowObjectiveService; | ||
50 | + | ||
51 | + private enum Direction { | ||
52 | + ADD, | ||
53 | + REMOVE | ||
54 | + } | ||
55 | + | ||
56 | + /** | ||
57 | + * Initializes the installer with references to required services. | ||
58 | + * | ||
59 | + * @param intentStore intent store | ||
60 | + * @param trackerService objective tracking service | ||
61 | + * @param flowRuleService flow rule service | ||
62 | + * @param flowObjectiveService flow objective service | ||
63 | + */ | ||
64 | + void init(IntentStore intentStore, ObjectiveTrackerService trackerService, | ||
65 | + FlowRuleService flowRuleService, FlowObjectiveService flowObjectiveService) { | ||
66 | + this.store = intentStore; | ||
67 | + this.trackerService = trackerService; | ||
68 | + this.flowRuleService = flowRuleService; | ||
69 | + this.flowObjectiveService = flowObjectiveService; | ||
70 | + } | ||
71 | + | ||
72 | + private void applyIntentData(Optional<IntentData> intentData, | ||
73 | + FlowRuleOperations.Builder builder, | ||
74 | + Direction direction) { | ||
75 | + if (!intentData.isPresent()) { | ||
76 | + return; | ||
77 | + } | ||
78 | + IntentData data = intentData.get(); | ||
79 | + | ||
80 | + List<Intent> intentsToApply = data.installables(); | ||
81 | + if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) { | ||
82 | + throw new IllegalStateException("installable intents must be FlowRuleIntent"); | ||
83 | + } | ||
84 | + | ||
85 | + if (direction == Direction.ADD) { | ||
86 | + trackerService.addTrackedResources(data.key(), data.intent().resources()); | ||
87 | + intentsToApply.forEach(installable -> | ||
88 | + trackerService.addTrackedResources(data.key(), installable.resources())); | ||
89 | + } else { | ||
90 | + trackerService.removeTrackedResources(data.key(), data.intent().resources()); | ||
91 | + intentsToApply.forEach(installable -> | ||
92 | + trackerService.removeTrackedResources(data.intent().key(), | ||
93 | + installable.resources())); | ||
94 | + } | ||
95 | + | ||
96 | + // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so. | ||
97 | + builder.newStage(); | ||
98 | + | ||
99 | + List<Collection<FlowRule>> stages = intentsToApply.stream() | ||
100 | + .map(x -> (FlowRuleIntent) x) | ||
101 | + .map(FlowRuleIntent::flowRules) | ||
102 | + .collect(Collectors.toList()); | ||
103 | + | ||
104 | + for (Collection<FlowRule> rules : stages) { | ||
105 | + if (direction == Direction.ADD) { | ||
106 | + rules.forEach(builder::add); | ||
107 | + } else { | ||
108 | + rules.forEach(builder::remove); | ||
109 | + } | ||
110 | + } | ||
111 | + | ||
112 | + } | ||
113 | + | ||
114 | + // FIXME: Refactor to accept both FlowObjectiveIntent and FlowRuleIntents | ||
115 | + // Note: Intent Manager should have never become dependent on a specific | ||
116 | + // intent type. | ||
117 | + | ||
118 | + /** | ||
119 | + * Applies the specified intent updates to the environment by uninstalling | ||
120 | + * and installing the intents and updating the store references appropriately. | ||
121 | + * | ||
122 | + * @param toUninstall optional intent to uninstall | ||
123 | + * @param toInstall optional intent to install | ||
124 | + */ | ||
125 | + void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) { | ||
126 | + // need to consider if FlowRuleIntent is only one as installable intent or not | ||
127 | + | ||
128 | + FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); | ||
129 | + applyIntentData(toUninstall, builder, Direction.REMOVE); | ||
130 | + applyIntentData(toInstall, builder, Direction.ADD); | ||
131 | + | ||
132 | + FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() { | ||
133 | + @Override | ||
134 | + public void onSuccess(FlowRuleOperations ops) { | ||
135 | + if (toInstall.isPresent()) { | ||
136 | + IntentData installData = toInstall.get(); | ||
137 | + log.debug("Completed installing: {}", installData.key()); | ||
138 | + installData.setState(INSTALLED); | ||
139 | + store.write(installData); | ||
140 | + } else if (toUninstall.isPresent()) { | ||
141 | + IntentData uninstallData = toUninstall.get(); | ||
142 | + log.debug("Completed withdrawing: {}", uninstallData.key()); | ||
143 | + switch (uninstallData.request()) { | ||
144 | + case INSTALL_REQ: | ||
145 | + uninstallData.setState(FAILED); | ||
146 | + break; | ||
147 | + case WITHDRAW_REQ: | ||
148 | + default: //TODO "default" case should not happen | ||
149 | + uninstallData.setState(WITHDRAWN); | ||
150 | + break; | ||
151 | + } | ||
152 | + store.write(uninstallData); | ||
153 | + } | ||
154 | + } | ||
155 | + | ||
156 | + @Override | ||
157 | + public void onError(FlowRuleOperations ops) { | ||
158 | + // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT) | ||
159 | + if (toInstall.isPresent()) { | ||
160 | + IntentData installData = toInstall.get(); | ||
161 | + log.warn("Failed installation: {} {} on {}", | ||
162 | + installData.key(), installData.intent(), ops); | ||
163 | + installData.setState(CORRUPT); | ||
164 | + installData.incrementErrorCount(); | ||
165 | + store.write(installData); | ||
166 | + } | ||
167 | + // if toUninstall was cause of error, then CORRUPT (another job will clean this up) | ||
168 | + if (toUninstall.isPresent()) { | ||
169 | + IntentData uninstallData = toUninstall.get(); | ||
170 | + log.warn("Failed withdrawal: {} {} on {}", | ||
171 | + uninstallData.key(), uninstallData.intent(), ops); | ||
172 | + uninstallData.setState(CORRUPT); | ||
173 | + uninstallData.incrementErrorCount(); | ||
174 | + store.write(uninstallData); | ||
175 | + } | ||
176 | + } | ||
177 | + }); | ||
178 | + | ||
179 | + if (log.isTraceEnabled()) { | ||
180 | + log.trace("applying intent {} -> {} with {} rules: {}", | ||
181 | + toUninstall.map(x -> x.key().toString()).orElse("<empty>"), | ||
182 | + toInstall.map(x -> x.key().toString()).orElse("<empty>"), | ||
183 | + operations.stages().stream().mapToLong(Set::size).sum(), | ||
184 | + operations.stages()); | ||
185 | + } | ||
186 | + | ||
187 | + flowRuleService.apply(operations); | ||
188 | + } | ||
189 | +} |
... | @@ -25,11 +25,8 @@ import org.onlab.util.Tools; | ... | @@ -25,11 +25,8 @@ import org.onlab.util.Tools; |
25 | import org.onosproject.core.CoreService; | 25 | import org.onosproject.core.CoreService; |
26 | import org.onosproject.core.IdGenerator; | 26 | import org.onosproject.core.IdGenerator; |
27 | import org.onosproject.event.AbstractListenerManager; | 27 | import org.onosproject.event.AbstractListenerManager; |
28 | -import org.onosproject.net.flow.FlowRule; | ||
29 | -import org.onosproject.net.flow.FlowRuleOperations; | ||
30 | -import org.onosproject.net.flow.FlowRuleOperationsContext; | ||
31 | import org.onosproject.net.flow.FlowRuleService; | 28 | import org.onosproject.net.flow.FlowRuleService; |
32 | -import org.onosproject.net.intent.FlowRuleIntent; | 29 | +import org.onosproject.net.flowobjective.FlowObjectiveService; |
33 | import org.onosproject.net.intent.Intent; | 30 | import org.onosproject.net.intent.Intent; |
34 | import org.onosproject.net.intent.IntentBatchDelegate; | 31 | import org.onosproject.net.intent.IntentBatchDelegate; |
35 | import org.onosproject.net.intent.IntentCompiler; | 32 | import org.onosproject.net.intent.IntentCompiler; |
... | @@ -61,13 +58,7 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -61,13 +58,7 @@ import static com.google.common.base.Preconditions.checkNotNull; |
61 | import static java.util.concurrent.Executors.newFixedThreadPool; | 58 | import static java.util.concurrent.Executors.newFixedThreadPool; |
62 | import static java.util.concurrent.Executors.newSingleThreadExecutor; | 59 | import static java.util.concurrent.Executors.newSingleThreadExecutor; |
63 | import static org.onlab.util.Tools.groupedThreads; | 60 | import static org.onlab.util.Tools.groupedThreads; |
64 | -import static org.onosproject.net.intent.IntentState.CORRUPT; | 61 | +import static org.onosproject.net.intent.IntentState.*; |
65 | -import static org.onosproject.net.intent.IntentState.FAILED; | ||
66 | -import static org.onosproject.net.intent.IntentState.INSTALLED; | ||
67 | -import static org.onosproject.net.intent.IntentState.INSTALL_REQ; | ||
68 | -import static org.onosproject.net.intent.IntentState.WITHDRAWING; | ||
69 | -import static org.onosproject.net.intent.IntentState.WITHDRAWN; | ||
70 | -import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ; | ||
71 | import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure; | 62 | import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure; |
72 | import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase; | 63 | import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase; |
73 | import static org.onosproject.security.AppGuard.checkPermission; | 64 | import static org.onosproject.security.AppGuard.checkPermission; |
... | @@ -75,7 +66,6 @@ import static org.onosproject.security.AppPermission.Type.INTENT_READ; | ... | @@ -75,7 +66,6 @@ import static org.onosproject.security.AppPermission.Type.INTENT_READ; |
75 | import static org.onosproject.security.AppPermission.Type.INTENT_WRITE; | 66 | import static org.onosproject.security.AppPermission.Type.INTENT_WRITE; |
76 | import static org.slf4j.LoggerFactory.getLogger; | 67 | import static org.slf4j.LoggerFactory.getLogger; |
77 | 68 | ||
78 | - | ||
79 | /** | 69 | /** |
80 | * An implementation of intent service. | 70 | * An implementation of intent service. |
81 | */ | 71 | */ |
... | @@ -110,11 +100,15 @@ public class IntentManager | ... | @@ -110,11 +100,15 @@ public class IntentManager |
110 | protected FlowRuleService flowRuleService; | 100 | protected FlowRuleService flowRuleService; |
111 | 101 | ||
112 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 102 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
103 | + protected FlowObjectiveService flowObjectiveService; | ||
104 | + | ||
105 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
113 | protected ResourceService resourceService; | 106 | protected ResourceService resourceService; |
114 | 107 | ||
115 | private ExecutorService batchExecutor; | 108 | private ExecutorService batchExecutor; |
116 | private ExecutorService workerExecutor; | 109 | private ExecutorService workerExecutor; |
117 | 110 | ||
111 | + private final IntentInstaller intentInstaller = new IntentInstaller(); | ||
118 | private final CompilerRegistry compilerRegistry = new CompilerRegistry(); | 112 | private final CompilerRegistry compilerRegistry = new CompilerRegistry(); |
119 | private final InternalIntentProcessor processor = new InternalIntentProcessor(); | 113 | private final InternalIntentProcessor processor = new InternalIntentProcessor(); |
120 | private final IntentStoreDelegate delegate = new InternalStoreDelegate(); | 114 | private final IntentStoreDelegate delegate = new InternalStoreDelegate(); |
... | @@ -126,6 +120,7 @@ public class IntentManager | ... | @@ -126,6 +120,7 @@ public class IntentManager |
126 | 120 | ||
127 | @Activate | 121 | @Activate |
128 | public void activate() { | 122 | public void activate() { |
123 | + intentInstaller.init(store, trackerService, flowRuleService, flowObjectiveService); | ||
129 | store.setDelegate(delegate); | 124 | store.setDelegate(delegate); |
130 | trackerService.setDelegate(topoDelegate); | 125 | trackerService.setDelegate(topoDelegate); |
131 | eventDispatcher.addSink(IntentEvent.class, listenerRegistry); | 126 | eventDispatcher.addSink(IntentEvent.class, listenerRegistry); |
... | @@ -138,6 +133,7 @@ public class IntentManager | ... | @@ -138,6 +133,7 @@ public class IntentManager |
138 | 133 | ||
139 | @Deactivate | 134 | @Deactivate |
140 | public void deactivate() { | 135 | public void deactivate() { |
136 | + intentInstaller.init(null, null, null, null); | ||
141 | store.unsetDelegate(delegate); | 137 | store.unsetDelegate(delegate); |
142 | trackerService.unsetDelegate(topoDelegate); | 138 | trackerService.unsetDelegate(topoDelegate); |
143 | eventDispatcher.removeSink(IntentEvent.class); | 139 | eventDispatcher.removeSink(IntentEvent.class); |
... | @@ -322,8 +318,8 @@ public class IntentManager | ... | @@ -322,8 +318,8 @@ public class IntentManager |
322 | 318 | ||
323 | // write multiple data to store in order | 319 | // write multiple data to store in order |
324 | store.batchWrite(Tools.allOf(futures).join().stream() | 320 | store.batchWrite(Tools.allOf(futures).join().stream() |
325 | - .filter(Objects::nonNull) | 321 | + .filter(Objects::nonNull) |
326 | - .collect(Collectors.toList())); | 322 | + .collect(Collectors.toList())); |
327 | }, batchExecutor).exceptionally(e -> { | 323 | }, batchExecutor).exceptionally(e -> { |
328 | log.error("Error submitting batches:", e); | 324 | log.error("Error submitting batches:", e); |
329 | // FIXME incomplete Intents should be cleaned up | 325 | // FIXME incomplete Intents should be cleaned up |
... | @@ -351,120 +347,8 @@ public class IntentManager | ... | @@ -351,120 +347,8 @@ public class IntentManager |
351 | 347 | ||
352 | @Override | 348 | @Override |
353 | public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) { | 349 | public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) { |
354 | - IntentManager.this.apply(toUninstall, toInstall); | 350 | + intentInstaller.apply(toUninstall, toInstall); |
355 | - } | ||
356 | - } | ||
357 | - | ||
358 | - private enum Direction { | ||
359 | - ADD, | ||
360 | - REMOVE | ||
361 | - } | ||
362 | - | ||
363 | - private void applyIntentData(Optional<IntentData> intentData, | ||
364 | - FlowRuleOperations.Builder builder, | ||
365 | - Direction direction) { | ||
366 | - if (!intentData.isPresent()) { | ||
367 | - return; | ||
368 | } | 351 | } |
369 | - IntentData data = intentData.get(); | ||
370 | - | ||
371 | - List<Intent> intentsToApply = data.installables(); | ||
372 | - if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) { | ||
373 | - throw new IllegalStateException("installable intents must be FlowRuleIntent"); | ||
374 | - } | ||
375 | - | ||
376 | - if (direction == Direction.ADD) { | ||
377 | - trackerService.addTrackedResources(data.key(), data.intent().resources()); | ||
378 | - intentsToApply.forEach(installable -> | ||
379 | - trackerService.addTrackedResources(data.key(), installable.resources())); | ||
380 | - } else { | ||
381 | - trackerService.removeTrackedResources(data.key(), data.intent().resources()); | ||
382 | - intentsToApply.forEach(installable -> | ||
383 | - trackerService.removeTrackedResources(data.intent().key(), | ||
384 | - installable.resources())); | ||
385 | - } | ||
386 | - | ||
387 | - // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so. | ||
388 | - builder.newStage(); | ||
389 | - | ||
390 | - List<Collection<FlowRule>> stages = intentsToApply.stream() | ||
391 | - .map(x -> (FlowRuleIntent) x) | ||
392 | - .map(FlowRuleIntent::flowRules) | ||
393 | - .collect(Collectors.toList()); | ||
394 | - | ||
395 | - for (Collection<FlowRule> rules : stages) { | ||
396 | - if (direction == Direction.ADD) { | ||
397 | - rules.forEach(builder::add); | ||
398 | - } else { | ||
399 | - rules.forEach(builder::remove); | ||
400 | - } | ||
401 | - } | ||
402 | - | ||
403 | - } | ||
404 | - | ||
405 | - private void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) { | ||
406 | - // need to consider if FlowRuleIntent is only one as installable intent or not | ||
407 | - | ||
408 | - FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); | ||
409 | - applyIntentData(toUninstall, builder, Direction.REMOVE); | ||
410 | - applyIntentData(toInstall, builder, Direction.ADD); | ||
411 | - | ||
412 | - FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() { | ||
413 | - @Override | ||
414 | - public void onSuccess(FlowRuleOperations ops) { | ||
415 | - if (toInstall.isPresent()) { | ||
416 | - IntentData installData = toInstall.get(); | ||
417 | - log.debug("Completed installing: {}", installData.key()); | ||
418 | - installData.setState(INSTALLED); | ||
419 | - store.write(installData); | ||
420 | - } else if (toUninstall.isPresent()) { | ||
421 | - IntentData uninstallData = toUninstall.get(); | ||
422 | - log.debug("Completed withdrawing: {}", uninstallData.key()); | ||
423 | - switch (uninstallData.request()) { | ||
424 | - case INSTALL_REQ: | ||
425 | - uninstallData.setState(FAILED); | ||
426 | - break; | ||
427 | - case WITHDRAW_REQ: | ||
428 | - default: //TODO "default" case should not happen | ||
429 | - uninstallData.setState(WITHDRAWN); | ||
430 | - break; | ||
431 | - } | ||
432 | - store.write(uninstallData); | ||
433 | - } | ||
434 | - } | ||
435 | - | ||
436 | - @Override | ||
437 | - public void onError(FlowRuleOperations ops) { | ||
438 | - // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT) | ||
439 | - if (toInstall.isPresent()) { | ||
440 | - IntentData installData = toInstall.get(); | ||
441 | - log.warn("Failed installation: {} {} on {}", | ||
442 | - installData.key(), installData.intent(), ops); | ||
443 | - installData.setState(CORRUPT); | ||
444 | - installData.incrementErrorCount(); | ||
445 | - store.write(installData); | ||
446 | - } | ||
447 | - // if toUninstall was cause of error, then CORRUPT (another job will clean this up) | ||
448 | - if (toUninstall.isPresent()) { | ||
449 | - IntentData uninstallData = toUninstall.get(); | ||
450 | - log.warn("Failed withdrawal: {} {} on {}", | ||
451 | - uninstallData.key(), uninstallData.intent(), ops); | ||
452 | - uninstallData.setState(CORRUPT); | ||
453 | - uninstallData.incrementErrorCount(); | ||
454 | - store.write(uninstallData); | ||
455 | - } | ||
456 | - } | ||
457 | - }); | ||
458 | - | ||
459 | - if (log.isTraceEnabled()) { | ||
460 | - log.trace("applying intent {} -> {} with {} rules: {}", | ||
461 | - toUninstall.map(x -> x.key().toString()).orElse("<empty>"), | ||
462 | - toInstall.map(x -> x.key().toString()).orElse("<empty>"), | ||
463 | - operations.stages().stream().mapToLong(i -> i.size()).sum(), | ||
464 | - operations.stages()); | ||
465 | - } | ||
466 | - | ||
467 | - flowRuleService.apply(operations); | ||
468 | } | 352 | } |
469 | 353 | ||
470 | } | 354 | } | ... | ... |
-
Please register or login to post a comment