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
395 additions
and
125 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); |
| ... | @@ -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 | - } | ||
| 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 | } | 351 | } |
| 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