mirror of
				https://github.com/opennetworkinglab/onos.git
				synced 2025-11-04 02:01:11 +01:00 
			
		
		
		
	Initial work for adding flow-objective backed intents.
Split installation work from IntentManager into IntentInstaller helper class. Change-Id: If926ce975d005abee4f22f2b05404de328d94203
This commit is contained in:
		
							parent
							
								
									b88b3f8bc6
								
							
						
					
					
						commit
						f6ec97b365
					
				@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2016 Open Networking Laboratory
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.onosproject.net.intent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.base.MoreObjects;
 | 
				
			||||||
 | 
					import org.onosproject.core.ApplicationId;
 | 
				
			||||||
 | 
					import org.onosproject.net.NetworkResource;
 | 
				
			||||||
 | 
					import org.onosproject.net.flowobjective.Objective;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Intent expressed as (and backed by) a collection of flow objectives through
 | 
				
			||||||
 | 
					 * which the intent is to be accomplished.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class FlowObjectiveIntent extends Intent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final Collection<Objective> objectives;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Constructor for serialization.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected FlowObjectiveIntent() {
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.objectives = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates a flow objective intent with the specified objectives and
 | 
				
			||||||
 | 
					     * resources.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param appId      application id
 | 
				
			||||||
 | 
					     * @param objectives backing flow objectives
 | 
				
			||||||
 | 
					     * @param resources  backing network resources
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public FlowObjectiveIntent(ApplicationId appId,
 | 
				
			||||||
 | 
					                               Collection<Objective> objectives,
 | 
				
			||||||
 | 
					                               Collection<NetworkResource> resources) {
 | 
				
			||||||
 | 
					        this(appId, null, objectives, resources);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates a flow objective intent with the specified objectives and
 | 
				
			||||||
 | 
					     * resources.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param appId      application id
 | 
				
			||||||
 | 
					     * @param key        intent key
 | 
				
			||||||
 | 
					     * @param objectives backing flow objectives
 | 
				
			||||||
 | 
					     * @param resources  backing network resources
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public FlowObjectiveIntent(ApplicationId appId, Key key,
 | 
				
			||||||
 | 
					                               Collection<Objective> objectives,
 | 
				
			||||||
 | 
					                               Collection<NetworkResource> resources) {
 | 
				
			||||||
 | 
					        super(appId, key, resources, DEFAULT_INTENT_PRIORITY);
 | 
				
			||||||
 | 
					        this.objectives = objectives;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns the collection of backing flow objectives.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return flow objectives
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Collection<Objective> objectives() {
 | 
				
			||||||
 | 
					        return objectives;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean isInstallable() {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String toString() {
 | 
				
			||||||
 | 
					        return MoreObjects.toStringHelper(this)
 | 
				
			||||||
 | 
					                .add("id", id())
 | 
				
			||||||
 | 
					                .add("key", key())
 | 
				
			||||||
 | 
					                .add("appId", appId())
 | 
				
			||||||
 | 
					                .add("resources", resources())
 | 
				
			||||||
 | 
					                .add("objectives", objectives)
 | 
				
			||||||
 | 
					                .toString();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -25,6 +25,7 @@ public abstract class AbstractIntentTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Before
 | 
					    @Before
 | 
				
			||||||
    public void setUp() throws Exception {
 | 
					    public void setUp() throws Exception {
 | 
				
			||||||
 | 
					        Intent.unbindIdGenerator(idGenerator);
 | 
				
			||||||
        Intent.bindIdGenerator(idGenerator);
 | 
					        Intent.bindIdGenerator(idGenerator);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2016 Open Networking Laboratory
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.onosproject.net.intent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.collect.ImmutableSet;
 | 
				
			||||||
 | 
					import com.google.common.testing.EqualsTester;
 | 
				
			||||||
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					import org.onosproject.core.ApplicationId;
 | 
				
			||||||
 | 
					import org.onosproject.core.DefaultApplicationId;
 | 
				
			||||||
 | 
					import org.onosproject.net.NetworkResource;
 | 
				
			||||||
 | 
					import org.onosproject.net.flow.DefaultTrafficSelector;
 | 
				
			||||||
 | 
					import org.onosproject.net.flow.DefaultTrafficTreatment;
 | 
				
			||||||
 | 
					import org.onosproject.net.flow.criteria.Criteria;
 | 
				
			||||||
 | 
					import org.onosproject.net.flowobjective.DefaultFilteringObjective;
 | 
				
			||||||
 | 
					import org.onosproject.net.flowobjective.DefaultForwardingObjective;
 | 
				
			||||||
 | 
					import org.onosproject.net.flowobjective.ForwardingObjective;
 | 
				
			||||||
 | 
					import org.onosproject.net.flowobjective.Objective;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.junit.Assert.assertEquals;
 | 
				
			||||||
 | 
					import static org.junit.Assert.assertTrue;
 | 
				
			||||||
 | 
					import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Tests of the flow objective intent.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class FlowObjectiveIntentTest extends IntentTest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final ApplicationId APP_ID = new DefaultApplicationId(1, "foo");
 | 
				
			||||||
 | 
					    private static final Key KEY = Key.of("bar", APP_ID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final Objective FO1 = DefaultFilteringObjective.builder()
 | 
				
			||||||
 | 
					            .fromApp(APP_ID).addCondition(Criteria.matchEthType(123))
 | 
				
			||||||
 | 
					            .permit().add();
 | 
				
			||||||
 | 
					    private static final Objective FO2 = DefaultForwardingObjective.builder()
 | 
				
			||||||
 | 
					            .fromApp(APP_ID)
 | 
				
			||||||
 | 
					            .withSelector(DefaultTrafficSelector.builder().matchEthType((short) 123).build())
 | 
				
			||||||
 | 
					            .withTreatment(DefaultTrafficTreatment.emptyTreatment())
 | 
				
			||||||
 | 
					            .withFlag(ForwardingObjective.Flag.VERSATILE).add();
 | 
				
			||||||
 | 
					    private static final Collection<Objective> OBJECTIVES = ImmutableSet.of(FO1, FO2);
 | 
				
			||||||
 | 
					    private static final Collection<NetworkResource> RESOURCES = ImmutableSet.of();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Tests basics of construction and getters.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void basics() {
 | 
				
			||||||
 | 
					        FlowObjectiveIntent intent =
 | 
				
			||||||
 | 
					                new FlowObjectiveIntent(APP_ID, KEY, OBJECTIVES, RESOURCES);
 | 
				
			||||||
 | 
					        assertEquals("incorrect app id", APP_ID, intent.appId());
 | 
				
			||||||
 | 
					        assertEquals("incorrect key", KEY, intent.key());
 | 
				
			||||||
 | 
					        assertEquals("incorrect objectives", OBJECTIVES, intent.objectives());
 | 
				
			||||||
 | 
					        assertEquals("incorrect resources", RESOURCES, intent.resources());
 | 
				
			||||||
 | 
					        assertTrue("should be installable", intent.isInstallable());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Tests equality.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void equality() {
 | 
				
			||||||
 | 
					        Intent a = createOne();
 | 
				
			||||||
 | 
					        Intent b = createAnother();
 | 
				
			||||||
 | 
					        new EqualsTester().addEqualityGroup(a).addEqualityGroup(b).testEquals();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Tests that instance is immutable.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void testImmutability() {
 | 
				
			||||||
 | 
					        assertThatClassIsImmutable(HostToHostIntent.class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected Intent createOne() {
 | 
				
			||||||
 | 
					        return new FlowObjectiveIntent(APP_ID, OBJECTIVES, RESOURCES);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected Intent createAnother() {
 | 
				
			||||||
 | 
					        return new FlowObjectiveIntent(APP_ID, OBJECTIVES, RESOURCES);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,189 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2016 Open Networking Laboratory
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.onosproject.net.intent.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.onosproject.net.flow.FlowRule;
 | 
				
			||||||
 | 
					import org.onosproject.net.flow.FlowRuleOperations;
 | 
				
			||||||
 | 
					import org.onosproject.net.flow.FlowRuleOperationsContext;
 | 
				
			||||||
 | 
					import org.onosproject.net.flow.FlowRuleService;
 | 
				
			||||||
 | 
					import org.onosproject.net.flowobjective.FlowObjectiveService;
 | 
				
			||||||
 | 
					import org.onosproject.net.intent.FlowRuleIntent;
 | 
				
			||||||
 | 
					import org.onosproject.net.intent.Intent;
 | 
				
			||||||
 | 
					import org.onosproject.net.intent.IntentData;
 | 
				
			||||||
 | 
					import org.onosproject.net.intent.IntentStore;
 | 
				
			||||||
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.onosproject.net.intent.IntentState.*;
 | 
				
			||||||
 | 
					import static org.slf4j.LoggerFactory.getLogger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Auxiliary entity responsible for installing the intents into the environment.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class IntentInstaller {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final Logger log = getLogger(IntentManager.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IntentStore store;
 | 
				
			||||||
 | 
					    private ObjectiveTrackerService trackerService;
 | 
				
			||||||
 | 
					    private FlowRuleService flowRuleService;
 | 
				
			||||||
 | 
					    private FlowObjectiveService flowObjectiveService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private enum Direction {
 | 
				
			||||||
 | 
					        ADD,
 | 
				
			||||||
 | 
					        REMOVE
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Initializes the installer with references to required services.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param intentStore          intent store
 | 
				
			||||||
 | 
					     * @param trackerService       objective tracking service
 | 
				
			||||||
 | 
					     * @param flowRuleService      flow rule service
 | 
				
			||||||
 | 
					     * @param flowObjectiveService flow objective service
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void init(IntentStore intentStore, ObjectiveTrackerService trackerService,
 | 
				
			||||||
 | 
					              FlowRuleService flowRuleService, FlowObjectiveService flowObjectiveService) {
 | 
				
			||||||
 | 
					        this.store = intentStore;
 | 
				
			||||||
 | 
					        this.trackerService = trackerService;
 | 
				
			||||||
 | 
					        this.flowRuleService = flowRuleService;
 | 
				
			||||||
 | 
					        this.flowObjectiveService = flowObjectiveService;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void applyIntentData(Optional<IntentData> intentData,
 | 
				
			||||||
 | 
					                                 FlowRuleOperations.Builder builder,
 | 
				
			||||||
 | 
					                                 Direction direction) {
 | 
				
			||||||
 | 
					        if (!intentData.isPresent()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        IntentData data = intentData.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        List<Intent> intentsToApply = data.installables();
 | 
				
			||||||
 | 
					        if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
 | 
				
			||||||
 | 
					            throw new IllegalStateException("installable intents must be FlowRuleIntent");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (direction == Direction.ADD) {
 | 
				
			||||||
 | 
					            trackerService.addTrackedResources(data.key(), data.intent().resources());
 | 
				
			||||||
 | 
					            intentsToApply.forEach(installable ->
 | 
				
			||||||
 | 
					                                           trackerService.addTrackedResources(data.key(), installable.resources()));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            trackerService.removeTrackedResources(data.key(), data.intent().resources());
 | 
				
			||||||
 | 
					            intentsToApply.forEach(installable ->
 | 
				
			||||||
 | 
					                                           trackerService.removeTrackedResources(data.intent().key(),
 | 
				
			||||||
 | 
					                                                                                 installable.resources()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so.
 | 
				
			||||||
 | 
					        builder.newStage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        List<Collection<FlowRule>> stages = intentsToApply.stream()
 | 
				
			||||||
 | 
					                .map(x -> (FlowRuleIntent) x)
 | 
				
			||||||
 | 
					                .map(FlowRuleIntent::flowRules)
 | 
				
			||||||
 | 
					                .collect(Collectors.toList());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (Collection<FlowRule> rules : stages) {
 | 
				
			||||||
 | 
					            if (direction == Direction.ADD) {
 | 
				
			||||||
 | 
					                rules.forEach(builder::add);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                rules.forEach(builder::remove);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // FIXME: Refactor to accept both FlowObjectiveIntent and FlowRuleIntents
 | 
				
			||||||
 | 
					    // Note: Intent Manager should have never become dependent on a specific
 | 
				
			||||||
 | 
					    // intent type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Applies the specified intent updates to the environment by uninstalling
 | 
				
			||||||
 | 
					     * and installing the intents and updating the store references appropriately.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param toUninstall optional intent to uninstall
 | 
				
			||||||
 | 
					     * @param toInstall   optional intent to install
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
 | 
				
			||||||
 | 
					        // need to consider if FlowRuleIntent is only one as installable intent or not
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
 | 
				
			||||||
 | 
					        applyIntentData(toUninstall, builder, Direction.REMOVE);
 | 
				
			||||||
 | 
					        applyIntentData(toInstall, builder, Direction.ADD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void onSuccess(FlowRuleOperations ops) {
 | 
				
			||||||
 | 
					                if (toInstall.isPresent()) {
 | 
				
			||||||
 | 
					                    IntentData installData = toInstall.get();
 | 
				
			||||||
 | 
					                    log.debug("Completed installing: {}", installData.key());
 | 
				
			||||||
 | 
					                    installData.setState(INSTALLED);
 | 
				
			||||||
 | 
					                    store.write(installData);
 | 
				
			||||||
 | 
					                } else if (toUninstall.isPresent()) {
 | 
				
			||||||
 | 
					                    IntentData uninstallData = toUninstall.get();
 | 
				
			||||||
 | 
					                    log.debug("Completed withdrawing: {}", uninstallData.key());
 | 
				
			||||||
 | 
					                    switch (uninstallData.request()) {
 | 
				
			||||||
 | 
					                        case INSTALL_REQ:
 | 
				
			||||||
 | 
					                            uninstallData.setState(FAILED);
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        case WITHDRAW_REQ:
 | 
				
			||||||
 | 
					                        default: //TODO "default" case should not happen
 | 
				
			||||||
 | 
					                            uninstallData.setState(WITHDRAWN);
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    store.write(uninstallData);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void onError(FlowRuleOperations ops) {
 | 
				
			||||||
 | 
					                // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT)
 | 
				
			||||||
 | 
					                if (toInstall.isPresent()) {
 | 
				
			||||||
 | 
					                    IntentData installData = toInstall.get();
 | 
				
			||||||
 | 
					                    log.warn("Failed installation: {} {} on {}",
 | 
				
			||||||
 | 
					                             installData.key(), installData.intent(), ops);
 | 
				
			||||||
 | 
					                    installData.setState(CORRUPT);
 | 
				
			||||||
 | 
					                    installData.incrementErrorCount();
 | 
				
			||||||
 | 
					                    store.write(installData);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                // if toUninstall was cause of error, then CORRUPT (another job will clean this up)
 | 
				
			||||||
 | 
					                if (toUninstall.isPresent()) {
 | 
				
			||||||
 | 
					                    IntentData uninstallData = toUninstall.get();
 | 
				
			||||||
 | 
					                    log.warn("Failed withdrawal: {} {} on {}",
 | 
				
			||||||
 | 
					                             uninstallData.key(), uninstallData.intent(), ops);
 | 
				
			||||||
 | 
					                    uninstallData.setState(CORRUPT);
 | 
				
			||||||
 | 
					                    uninstallData.incrementErrorCount();
 | 
				
			||||||
 | 
					                    store.write(uninstallData);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (log.isTraceEnabled()) {
 | 
				
			||||||
 | 
					            log.trace("applying intent {} -> {} with {} rules: {}",
 | 
				
			||||||
 | 
					                      toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
 | 
				
			||||||
 | 
					                      toInstall.map(x -> x.key().toString()).orElse("<empty>"),
 | 
				
			||||||
 | 
					                      operations.stages().stream().mapToLong(Set::size).sum(),
 | 
				
			||||||
 | 
					                      operations.stages());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        flowRuleService.apply(operations);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -25,11 +25,8 @@ import org.onlab.util.Tools;
 | 
				
			|||||||
import org.onosproject.core.CoreService;
 | 
					import org.onosproject.core.CoreService;
 | 
				
			||||||
import org.onosproject.core.IdGenerator;
 | 
					import org.onosproject.core.IdGenerator;
 | 
				
			||||||
import org.onosproject.event.AbstractListenerManager;
 | 
					import org.onosproject.event.AbstractListenerManager;
 | 
				
			||||||
import org.onosproject.net.flow.FlowRule;
 | 
					 | 
				
			||||||
import org.onosproject.net.flow.FlowRuleOperations;
 | 
					 | 
				
			||||||
import org.onosproject.net.flow.FlowRuleOperationsContext;
 | 
					 | 
				
			||||||
import org.onosproject.net.flow.FlowRuleService;
 | 
					import org.onosproject.net.flow.FlowRuleService;
 | 
				
			||||||
import org.onosproject.net.intent.FlowRuleIntent;
 | 
					import org.onosproject.net.flowobjective.FlowObjectiveService;
 | 
				
			||||||
import org.onosproject.net.intent.Intent;
 | 
					import org.onosproject.net.intent.Intent;
 | 
				
			||||||
import org.onosproject.net.intent.IntentBatchDelegate;
 | 
					import org.onosproject.net.intent.IntentBatchDelegate;
 | 
				
			||||||
import org.onosproject.net.intent.IntentCompiler;
 | 
					import org.onosproject.net.intent.IntentCompiler;
 | 
				
			||||||
@ -61,13 +58,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 | 
				
			|||||||
import static java.util.concurrent.Executors.newFixedThreadPool;
 | 
					import static java.util.concurrent.Executors.newFixedThreadPool;
 | 
				
			||||||
import static java.util.concurrent.Executors.newSingleThreadExecutor;
 | 
					import static java.util.concurrent.Executors.newSingleThreadExecutor;
 | 
				
			||||||
import static org.onlab.util.Tools.groupedThreads;
 | 
					import static org.onlab.util.Tools.groupedThreads;
 | 
				
			||||||
import static org.onosproject.net.intent.IntentState.CORRUPT;
 | 
					import static org.onosproject.net.intent.IntentState.*;
 | 
				
			||||||
import static org.onosproject.net.intent.IntentState.FAILED;
 | 
					 | 
				
			||||||
import static org.onosproject.net.intent.IntentState.INSTALLED;
 | 
					 | 
				
			||||||
import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
 | 
					 | 
				
			||||||
import static org.onosproject.net.intent.IntentState.WITHDRAWING;
 | 
					 | 
				
			||||||
import static org.onosproject.net.intent.IntentState.WITHDRAWN;
 | 
					 | 
				
			||||||
import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
 | 
					 | 
				
			||||||
import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
 | 
					import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
 | 
				
			||||||
import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
 | 
					import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
 | 
				
			||||||
import static org.onosproject.security.AppGuard.checkPermission;
 | 
					import static org.onosproject.security.AppGuard.checkPermission;
 | 
				
			||||||
@ -75,7 +66,6 @@ import static org.onosproject.security.AppPermission.Type.INTENT_READ;
 | 
				
			|||||||
import static org.onosproject.security.AppPermission.Type.INTENT_WRITE;
 | 
					import static org.onosproject.security.AppPermission.Type.INTENT_WRITE;
 | 
				
			||||||
import static org.slf4j.LoggerFactory.getLogger;
 | 
					import static org.slf4j.LoggerFactory.getLogger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * An implementation of intent service.
 | 
					 * An implementation of intent service.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -109,12 +99,16 @@ public class IntentManager
 | 
				
			|||||||
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
					    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
				
			||||||
    protected FlowRuleService flowRuleService;
 | 
					    protected FlowRuleService flowRuleService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
				
			||||||
 | 
					    protected FlowObjectiveService flowObjectiveService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
					    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
				
			||||||
    protected ResourceService resourceService;
 | 
					    protected ResourceService resourceService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ExecutorService batchExecutor;
 | 
					    private ExecutorService batchExecutor;
 | 
				
			||||||
    private ExecutorService workerExecutor;
 | 
					    private ExecutorService workerExecutor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final IntentInstaller intentInstaller = new IntentInstaller();
 | 
				
			||||||
    private final CompilerRegistry compilerRegistry = new CompilerRegistry();
 | 
					    private final CompilerRegistry compilerRegistry = new CompilerRegistry();
 | 
				
			||||||
    private final InternalIntentProcessor processor = new InternalIntentProcessor();
 | 
					    private final InternalIntentProcessor processor = new InternalIntentProcessor();
 | 
				
			||||||
    private final IntentStoreDelegate delegate = new InternalStoreDelegate();
 | 
					    private final IntentStoreDelegate delegate = new InternalStoreDelegate();
 | 
				
			||||||
@ -126,6 +120,7 @@ public class IntentManager
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Activate
 | 
					    @Activate
 | 
				
			||||||
    public void activate() {
 | 
					    public void activate() {
 | 
				
			||||||
 | 
					        intentInstaller.init(store, trackerService, flowRuleService, flowObjectiveService);
 | 
				
			||||||
        store.setDelegate(delegate);
 | 
					        store.setDelegate(delegate);
 | 
				
			||||||
        trackerService.setDelegate(topoDelegate);
 | 
					        trackerService.setDelegate(topoDelegate);
 | 
				
			||||||
        eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
 | 
					        eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
 | 
				
			||||||
@ -138,6 +133,7 @@ public class IntentManager
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Deactivate
 | 
					    @Deactivate
 | 
				
			||||||
    public void deactivate() {
 | 
					    public void deactivate() {
 | 
				
			||||||
 | 
					        intentInstaller.init(null, null, null, null);
 | 
				
			||||||
        store.unsetDelegate(delegate);
 | 
					        store.unsetDelegate(delegate);
 | 
				
			||||||
        trackerService.unsetDelegate(topoDelegate);
 | 
					        trackerService.unsetDelegate(topoDelegate);
 | 
				
			||||||
        eventDispatcher.removeSink(IntentEvent.class);
 | 
					        eventDispatcher.removeSink(IntentEvent.class);
 | 
				
			||||||
@ -322,8 +318,8 @@ public class IntentManager
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // write multiple data to store in order
 | 
					                // write multiple data to store in order
 | 
				
			||||||
                store.batchWrite(Tools.allOf(futures).join().stream()
 | 
					                store.batchWrite(Tools.allOf(futures).join().stream()
 | 
				
			||||||
                        .filter(Objects::nonNull)
 | 
					                                         .filter(Objects::nonNull)
 | 
				
			||||||
                        .collect(Collectors.toList()));
 | 
					                                         .collect(Collectors.toList()));
 | 
				
			||||||
            }, batchExecutor).exceptionally(e -> {
 | 
					            }, batchExecutor).exceptionally(e -> {
 | 
				
			||||||
                log.error("Error submitting batches:", e);
 | 
					                log.error("Error submitting batches:", e);
 | 
				
			||||||
                // FIXME incomplete Intents should be cleaned up
 | 
					                // FIXME incomplete Intents should be cleaned up
 | 
				
			||||||
@ -351,120 +347,8 @@ public class IntentManager
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
 | 
					        public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
 | 
				
			||||||
            IntentManager.this.apply(toUninstall, toInstall);
 | 
					            intentInstaller.apply(toUninstall, toInstall);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private enum Direction {
 | 
					 | 
				
			||||||
        ADD,
 | 
					 | 
				
			||||||
        REMOVE
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void applyIntentData(Optional<IntentData> intentData,
 | 
					 | 
				
			||||||
                                 FlowRuleOperations.Builder builder,
 | 
					 | 
				
			||||||
                                 Direction direction) {
 | 
					 | 
				
			||||||
        if (!intentData.isPresent()) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        IntentData data = intentData.get();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        List<Intent> intentsToApply = data.installables();
 | 
					 | 
				
			||||||
        if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
 | 
					 | 
				
			||||||
            throw new IllegalStateException("installable intents must be FlowRuleIntent");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (direction == Direction.ADD) {
 | 
					 | 
				
			||||||
            trackerService.addTrackedResources(data.key(), data.intent().resources());
 | 
					 | 
				
			||||||
            intentsToApply.forEach(installable ->
 | 
					 | 
				
			||||||
                    trackerService.addTrackedResources(data.key(), installable.resources()));
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            trackerService.removeTrackedResources(data.key(), data.intent().resources());
 | 
					 | 
				
			||||||
            intentsToApply.forEach(installable ->
 | 
					 | 
				
			||||||
                    trackerService.removeTrackedResources(data.intent().key(),
 | 
					 | 
				
			||||||
                            installable.resources()));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so.
 | 
					 | 
				
			||||||
        builder.newStage();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        List<Collection<FlowRule>> stages = intentsToApply.stream()
 | 
					 | 
				
			||||||
                .map(x -> (FlowRuleIntent) x)
 | 
					 | 
				
			||||||
                .map(FlowRuleIntent::flowRules)
 | 
					 | 
				
			||||||
                .collect(Collectors.toList());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (Collection<FlowRule> rules : stages) {
 | 
					 | 
				
			||||||
            if (direction == Direction.ADD) {
 | 
					 | 
				
			||||||
                rules.forEach(builder::add);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                rules.forEach(builder::remove);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
 | 
					 | 
				
			||||||
        // need to consider if FlowRuleIntent is only one as installable intent or not
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
 | 
					 | 
				
			||||||
        applyIntentData(toUninstall, builder, Direction.REMOVE);
 | 
					 | 
				
			||||||
        applyIntentData(toInstall, builder, Direction.ADD);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
 | 
					 | 
				
			||||||
            @Override
 | 
					 | 
				
			||||||
            public void onSuccess(FlowRuleOperations ops) {
 | 
					 | 
				
			||||||
                if (toInstall.isPresent()) {
 | 
					 | 
				
			||||||
                    IntentData installData = toInstall.get();
 | 
					 | 
				
			||||||
                    log.debug("Completed installing: {}", installData.key());
 | 
					 | 
				
			||||||
                    installData.setState(INSTALLED);
 | 
					 | 
				
			||||||
                    store.write(installData);
 | 
					 | 
				
			||||||
                } else if (toUninstall.isPresent()) {
 | 
					 | 
				
			||||||
                    IntentData uninstallData = toUninstall.get();
 | 
					 | 
				
			||||||
                    log.debug("Completed withdrawing: {}", uninstallData.key());
 | 
					 | 
				
			||||||
                    switch (uninstallData.request()) {
 | 
					 | 
				
			||||||
                        case INSTALL_REQ:
 | 
					 | 
				
			||||||
                            uninstallData.setState(FAILED);
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                        case WITHDRAW_REQ:
 | 
					 | 
				
			||||||
                        default: //TODO "default" case should not happen
 | 
					 | 
				
			||||||
                            uninstallData.setState(WITHDRAWN);
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    store.write(uninstallData);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            @Override
 | 
					 | 
				
			||||||
            public void onError(FlowRuleOperations ops) {
 | 
					 | 
				
			||||||
                // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT)
 | 
					 | 
				
			||||||
                if (toInstall.isPresent()) {
 | 
					 | 
				
			||||||
                    IntentData installData = toInstall.get();
 | 
					 | 
				
			||||||
                    log.warn("Failed installation: {} {} on {}",
 | 
					 | 
				
			||||||
                             installData.key(), installData.intent(), ops);
 | 
					 | 
				
			||||||
                    installData.setState(CORRUPT);
 | 
					 | 
				
			||||||
                    installData.incrementErrorCount();
 | 
					 | 
				
			||||||
                    store.write(installData);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                // if toUninstall was cause of error, then CORRUPT (another job will clean this up)
 | 
					 | 
				
			||||||
                if (toUninstall.isPresent()) {
 | 
					 | 
				
			||||||
                    IntentData uninstallData = toUninstall.get();
 | 
					 | 
				
			||||||
                    log.warn("Failed withdrawal: {} {} on {}",
 | 
					 | 
				
			||||||
                             uninstallData.key(), uninstallData.intent(), ops);
 | 
					 | 
				
			||||||
                    uninstallData.setState(CORRUPT);
 | 
					 | 
				
			||||||
                    uninstallData.incrementErrorCount();
 | 
					 | 
				
			||||||
                    store.write(uninstallData);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (log.isTraceEnabled()) {
 | 
					 | 
				
			||||||
            log.trace("applying intent {} -> {} with {} rules: {}",
 | 
					 | 
				
			||||||
                    toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
 | 
					 | 
				
			||||||
                    toInstall.map(x -> x.key().toString()).orElse("<empty>"),
 | 
					 | 
				
			||||||
                    operations.stages().stream().mapToLong(i -> i.size()).sum(),
 | 
					 | 
				
			||||||
                    operations.stages());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        flowRuleService.apply(operations);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user