mirror of
				https://github.com/opennetworkinglab/onos.git
				synced 2025-11-04 10:11:16 +01:00 
			
		
		
		
	[ONOS-6556] Distributed Implementation of PiPipeconfService
Change-Id: I7196ce6eee333e732c0cd5015d4d8d32ee069e27
This commit is contained in:
		
							parent
							
								
									7f8d14db82
								
							
						
					
					
						commit
						f9c409a3d8
					
				@ -134,7 +134,7 @@ public class DistributedDhcpRelayStoreTest {
 | 
				
			|||||||
        assertEquals(record.ip6Status(), removedRecord.ip6Status());
 | 
					        assertEquals(record.ip6Status(), removedRecord.ip6Status());
 | 
				
			||||||
        assertEquals(record.directlyConnected(), removedRecord.directlyConnected());
 | 
					        assertEquals(record.directlyConnected(), removedRecord.directlyConnected());
 | 
				
			||||||
        event = recordComplete.join();
 | 
					        event = recordComplete.join();
 | 
				
			||||||
        assertEquals(null, event.subject());
 | 
					        assertEquals(record, event.subject());
 | 
				
			||||||
        assertEquals(DhcpRelayStoreEvent.Type.REMOVED, event.type());
 | 
					        assertEquals(DhcpRelayStoreEvent.Type.REMOVED, event.type());
 | 
				
			||||||
        recordInStore = store.getDhcpRecord(HOST_ID).orElse(null);
 | 
					        recordInStore = store.getDhcpRecord(HOST_ID).orElse(null);
 | 
				
			||||||
        assertNull(recordInStore);
 | 
					        assertNull(recordInStore);
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017-present Open Networking Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.pi.runtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.annotations.Beta;
 | 
				
			||||||
 | 
					import org.onosproject.event.AbstractEvent;
 | 
				
			||||||
 | 
					import org.onosproject.net.DeviceId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Entity that represents pipeconf to device binding events.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Beta
 | 
				
			||||||
 | 
					public class PiPipeconfDeviceMappingEvent extends AbstractEvent<PiPipeconfDeviceMappingEvent.Type, DeviceId> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Type of pipeconf to device mapping event.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public enum Type {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Individual mapping pipeconf to device added.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        CREATED,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Individual mapping pipeconf to device removed.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        REMOVED,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates an event due to one Pipeconf being mapped to a device.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param type     event type
 | 
				
			||||||
 | 
					     * @param deviceId the deviceId for which the pipeconf was bound or updated.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public PiPipeconfDeviceMappingEvent(PiPipeconfDeviceMappingEvent.Type type, DeviceId deviceId) {
 | 
				
			||||||
 | 
					        super(type, deviceId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017-present Open Networking Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.pi.runtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.annotations.Beta;
 | 
				
			||||||
 | 
					import org.onosproject.net.DeviceId;
 | 
				
			||||||
 | 
					import org.onosproject.net.pi.model.PiPipeconfId;
 | 
				
			||||||
 | 
					import org.onosproject.store.Store;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Manages the mapping of Pipeconfs that are deployed to devices; not intended for direct use.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Beta
 | 
				
			||||||
 | 
					public interface PiPipeconfMappingStore extends Store<PiPipeconfDeviceMappingEvent, PiPipeconfMappingStoreDelegate> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Retrieves the id of the pipeconf deployed on a given device.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param deviceId device identifier
 | 
				
			||||||
 | 
					     * @return PiPipeconfId
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PiPipeconfId getPipeconfId(DeviceId deviceId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Retrieves the set of devices on which the given pipeconf is applied.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param pipeconfId pipeconf identifier
 | 
				
			||||||
 | 
					     * @return the set of devices that have that pipeconf applied.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Set<DeviceId> getDevices(PiPipeconfId pipeconfId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Stores or updates a binding between a device and the pipeconf deployed on it.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param deviceId   deviceId
 | 
				
			||||||
 | 
					     * @param pipeconfId pipeconfId
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void createOrUpdateBinding(DeviceId deviceId, PiPipeconfId pipeconfId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Removes device to pipeconf binding.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param deviceId deviceId
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void removeBinding(DeviceId deviceId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017-present Open Networking Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.pi.runtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.annotations.Beta;
 | 
				
			||||||
 | 
					import org.onosproject.store.StoreDelegate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Pipeconf store delegate abstraction.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Beta
 | 
				
			||||||
 | 
					public interface PiPipeconfMappingStoreDelegate extends StoreDelegate<PiPipeconfDeviceMappingEvent> {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -89,4 +89,5 @@ public interface PiPipeconfService {
 | 
				
			|||||||
     * @return an optional pipeconf identifier
 | 
					     * @return an optional pipeconf identifier
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    Optional<PiPipeconfId> ofDevice(DeviceId deviceId);
 | 
					    Optional<PiPipeconfId> ofDevice(DeviceId deviceId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -103,7 +103,7 @@ public final class TestEventuallyConsistentMap<K, V> extends EventuallyConsisten
 | 
				
			|||||||
        if (result != null) {
 | 
					        if (result != null) {
 | 
				
			||||||
            EventuallyConsistentMapEvent<K, V> removeEvent =
 | 
					            EventuallyConsistentMapEvent<K, V> removeEvent =
 | 
				
			||||||
                    new EventuallyConsistentMapEvent<>(mapName, REMOVE,
 | 
					                    new EventuallyConsistentMapEvent<>(mapName, REMOVE,
 | 
				
			||||||
                            key, map.get(key));
 | 
					                            key, result);
 | 
				
			||||||
            notifyListeners(removeEvent);
 | 
					            notifyListeners(removeEvent);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,7 @@ import org.onosproject.net.driver.DriverService;
 | 
				
			|||||||
import org.onosproject.net.pi.model.PiPipeconf;
 | 
					import org.onosproject.net.pi.model.PiPipeconf;
 | 
				
			||||||
import org.onosproject.net.pi.model.PiPipeconfId;
 | 
					import org.onosproject.net.pi.model.PiPipeconfId;
 | 
				
			||||||
import org.onosproject.net.pi.runtime.PiPipeconfConfig;
 | 
					import org.onosproject.net.pi.runtime.PiPipeconfConfig;
 | 
				
			||||||
 | 
					import org.onosproject.net.pi.runtime.PiPipeconfMappingStore;
 | 
				
			||||||
import org.onosproject.net.pi.runtime.PiPipeconfService;
 | 
					import org.onosproject.net.pi.runtime.PiPipeconfService;
 | 
				
			||||||
import org.slf4j.Logger;
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -83,10 +84,11 @@ public class PiPipeconfManager implements PiPipeconfService {
 | 
				
			|||||||
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
					    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
				
			||||||
    protected DriverAdminService driverAdminService;
 | 
					    protected DriverAdminService driverAdminService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //TODO move to replicated map
 | 
					    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
				
			||||||
 | 
					    protected PiPipeconfMappingStore pipeconfMappingStore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Registered pipeconf are replicated through the app subsystem and registered on app activated events.
 | 
				
			||||||
    protected ConcurrentHashMap<PiPipeconfId, PiPipeconf> piPipeconfs = new ConcurrentHashMap<>();
 | 
					    protected ConcurrentHashMap<PiPipeconfId, PiPipeconf> piPipeconfs = new ConcurrentHashMap<>();
 | 
				
			||||||
    //TODO move to replicated map
 | 
					 | 
				
			||||||
    protected ConcurrentHashMap<DeviceId, PiPipeconfId> devicesToPipeconf = new ConcurrentHashMap<>();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected ExecutorService executor =
 | 
					    protected ExecutorService executor =
 | 
				
			||||||
            Executors.newFixedThreadPool(5, groupedThreads("onos/pipipeconfservice",
 | 
					            Executors.newFixedThreadPool(5, groupedThreads("onos/pipipeconfservice",
 | 
				
			||||||
@ -120,7 +122,6 @@ public class PiPipeconfManager implements PiPipeconfService {
 | 
				
			|||||||
        cfgService.removeListener(cfgListener);
 | 
					        cfgService.removeListener(cfgListener);
 | 
				
			||||||
        cfgService.unregisterConfigFactory(factory);
 | 
					        cfgService.unregisterConfigFactory(factory);
 | 
				
			||||||
        piPipeconfs.clear();
 | 
					        piPipeconfs.clear();
 | 
				
			||||||
        devicesToPipeconf.clear();
 | 
					 | 
				
			||||||
        cfgService = null;
 | 
					        cfgService = null;
 | 
				
			||||||
        driverAdminService = null;
 | 
					        driverAdminService = null;
 | 
				
			||||||
        driverService = null;
 | 
					        driverService = null;
 | 
				
			||||||
@ -139,11 +140,12 @@ public class PiPipeconfManager implements PiPipeconfService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void remove(PiPipeconfId pipeconfId) throws IllegalStateException {
 | 
					    public void remove(PiPipeconfId pipeconfId) throws IllegalStateException {
 | 
				
			||||||
        //TODO move to the distributed mechanism
 | 
					 | 
				
			||||||
        //TODO add mechanism to remove from device.
 | 
					        //TODO add mechanism to remove from device.
 | 
				
			||||||
        if (!piPipeconfs.containsKey(pipeconfId)) {
 | 
					        if (!piPipeconfs.containsKey(pipeconfId)) {
 | 
				
			||||||
            throw new IllegalStateException(format("Pipeconf %s is not registered", pipeconfId));
 | 
					            throw new IllegalStateException(format("Pipeconf %s is not registered", pipeconfId));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        // TODO remove the binding from the distributed Store when the lifecycle of a pipeconf is defined.
 | 
				
			||||||
 | 
					        // pipeconfMappingStore.removeBindings(pipeconfId);
 | 
				
			||||||
        piPipeconfs.remove(pipeconfId);
 | 
					        piPipeconfs.remove(pipeconfId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -212,7 +214,7 @@ public class PiPipeconfManager implements PiPipeconfService {
 | 
				
			|||||||
                // Completable future is needed for when this method will also apply the pipeline to the device.
 | 
					                // Completable future is needed for when this method will also apply the pipeline to the device.
 | 
				
			||||||
                // FIXME (maybe): the pipeline is currently applied by the general device provider. But we store here
 | 
					                // FIXME (maybe): the pipeline is currently applied by the general device provider. But we store here
 | 
				
			||||||
                // the association between device and pipeconf.
 | 
					                // the association between device and pipeconf.
 | 
				
			||||||
                devicesToPipeconf.put(deviceId, pipeconfId);
 | 
					                pipeconfMappingStore.createOrUpdateBinding(deviceId, pipeconfId);
 | 
				
			||||||
                operationResult.complete(true);
 | 
					                operationResult.complete(true);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -221,9 +223,10 @@ public class PiPipeconfManager implements PiPipeconfService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Optional<PiPipeconfId> ofDevice(DeviceId deviceId) {
 | 
					    public Optional<PiPipeconfId> ofDevice(DeviceId deviceId) {
 | 
				
			||||||
        return Optional.ofNullable(devicesToPipeconf.get(deviceId));
 | 
					        return Optional.ofNullable(pipeconfMappingStore.getPipeconfId(deviceId));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private class PiPipeconfDriverProviderInternal implements DriverProvider {
 | 
					    private class PiPipeconfDriverProviderInternal implements DriverProvider {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Driver driver;
 | 
					        Driver driver;
 | 
				
			||||||
@ -245,7 +248,7 @@ public class PiPipeconfManager implements PiPipeconfService {
 | 
				
			|||||||
        if (id.id().equals("")) {
 | 
					        if (id.id().equals("")) {
 | 
				
			||||||
            log.warn("Not adding empty pipeconfId for device {}", deviceId);
 | 
					            log.warn("Not adding empty pipeconfId for device {}", deviceId);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            devicesToPipeconf.put(deviceId, pipeconfConfig.piPipeconfId());
 | 
					            pipeconfMappingStore.createOrUpdateBinding(deviceId, id);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,142 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017-present Open Networking Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.store.pi.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.collect.Sets;
 | 
				
			||||||
 | 
					import org.apache.felix.scr.annotations.Activate;
 | 
				
			||||||
 | 
					import org.apache.felix.scr.annotations.Component;
 | 
				
			||||||
 | 
					import org.apache.felix.scr.annotations.Deactivate;
 | 
				
			||||||
 | 
					import org.apache.felix.scr.annotations.Reference;
 | 
				
			||||||
 | 
					import org.apache.felix.scr.annotations.ReferenceCardinality;
 | 
				
			||||||
 | 
					import org.apache.felix.scr.annotations.Service;
 | 
				
			||||||
 | 
					import org.onlab.util.KryoNamespace;
 | 
				
			||||||
 | 
					import org.onosproject.net.DeviceId;
 | 
				
			||||||
 | 
					import org.onosproject.net.pi.model.PiPipeconfId;
 | 
				
			||||||
 | 
					import org.onosproject.net.pi.runtime.PiPipeconfDeviceMappingEvent;
 | 
				
			||||||
 | 
					import org.onosproject.net.pi.runtime.PiPipeconfMappingStore;
 | 
				
			||||||
 | 
					import org.onosproject.net.pi.runtime.PiPipeconfMappingStoreDelegate;
 | 
				
			||||||
 | 
					import org.onosproject.store.AbstractStore;
 | 
				
			||||||
 | 
					import org.onosproject.store.serializers.KryoNamespaces;
 | 
				
			||||||
 | 
					import org.onosproject.store.service.EventuallyConsistentMap;
 | 
				
			||||||
 | 
					import org.onosproject.store.service.EventuallyConsistentMapEvent;
 | 
				
			||||||
 | 
					import org.onosproject.store.service.EventuallyConsistentMapListener;
 | 
				
			||||||
 | 
					import org.onosproject.store.service.MultiValuedTimestamp;
 | 
				
			||||||
 | 
					import org.onosproject.store.service.StorageService;
 | 
				
			||||||
 | 
					import org.onosproject.store.service.WallClockTimestamp;
 | 
				
			||||||
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					import java.util.concurrent.ConcurrentHashMap;
 | 
				
			||||||
 | 
					import java.util.concurrent.ConcurrentMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.slf4j.LoggerFactory.getLogger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Manages information of pipeconf to device binding using gossip protocol to distribute
 | 
				
			||||||
 | 
					 * information.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Component(immediate = true)
 | 
				
			||||||
 | 
					@Service
 | 
				
			||||||
 | 
					public class DistributedDevicePipeconfMappingStore
 | 
				
			||||||
 | 
					        extends AbstractStore<PiPipeconfDeviceMappingEvent, PiPipeconfMappingStoreDelegate>
 | 
				
			||||||
 | 
					        implements PiPipeconfMappingStore {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final Logger log = getLogger(getClass());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
 | 
				
			||||||
 | 
					    protected StorageService storageService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected EventuallyConsistentMap<DeviceId, PiPipeconfId> deviceToPipeconf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected final EventuallyConsistentMapListener<DeviceId, PiPipeconfId> pipeconfListener =
 | 
				
			||||||
 | 
					            new InternalPiPipeconfListener();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected ConcurrentMap<PiPipeconfId, Set<DeviceId>> pipeconfToDevices = new ConcurrentHashMap<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Activate
 | 
				
			||||||
 | 
					    public void activate() {
 | 
				
			||||||
 | 
					        KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
 | 
				
			||||||
 | 
					                .register(KryoNamespaces.API)
 | 
				
			||||||
 | 
					                .register(MultiValuedTimestamp.class);
 | 
				
			||||||
 | 
					        deviceToPipeconf = storageService.<DeviceId, PiPipeconfId>eventuallyConsistentMapBuilder()
 | 
				
			||||||
 | 
					                .withName("onos-pipeconf-table")
 | 
				
			||||||
 | 
					                .withSerializer(serializer)
 | 
				
			||||||
 | 
					                .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();
 | 
				
			||||||
 | 
					        deviceToPipeconf.addListener(pipeconfListener);
 | 
				
			||||||
 | 
					        log.info("Started");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Deactivate
 | 
				
			||||||
 | 
					    public void deactivate() {
 | 
				
			||||||
 | 
					        deviceToPipeconf.removeListener(pipeconfListener);
 | 
				
			||||||
 | 
					        deviceToPipeconf = null;
 | 
				
			||||||
 | 
					        pipeconfToDevices = null;
 | 
				
			||||||
 | 
					        log.info("Stopped");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public PiPipeconfId getPipeconfId(DeviceId deviceId) {
 | 
				
			||||||
 | 
					        return deviceToPipeconf.get(deviceId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Set<DeviceId> getDevices(PiPipeconfId pipeconfId) {
 | 
				
			||||||
 | 
					        return pipeconfToDevices.get(pipeconfId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void createOrUpdateBinding(DeviceId deviceId, PiPipeconfId pipeconfId) {
 | 
				
			||||||
 | 
					        deviceToPipeconf.put(deviceId, pipeconfId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void removeBinding(DeviceId deviceId) {
 | 
				
			||||||
 | 
					        deviceToPipeconf.remove(deviceId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private class InternalPiPipeconfListener implements EventuallyConsistentMapListener<DeviceId, PiPipeconfId> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void event(EventuallyConsistentMapEvent<DeviceId, PiPipeconfId> mapEvent) {
 | 
				
			||||||
 | 
					            final PiPipeconfDeviceMappingEvent.Type type;
 | 
				
			||||||
 | 
					            final DeviceId deviceId = mapEvent.key();
 | 
				
			||||||
 | 
					            final PiPipeconfId pipeconfId = mapEvent.value();
 | 
				
			||||||
 | 
					            switch (mapEvent.type()) {
 | 
				
			||||||
 | 
					                case PUT:
 | 
				
			||||||
 | 
					                    type = PiPipeconfDeviceMappingEvent.Type.CREATED;
 | 
				
			||||||
 | 
					                    pipeconfToDevices.compute(pipeconfId, (pipeconf, devices) -> {
 | 
				
			||||||
 | 
					                        if (devices == null) {
 | 
				
			||||||
 | 
					                            devices = Sets.newConcurrentHashSet();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        devices.add(deviceId);
 | 
				
			||||||
 | 
					                        return devices;
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case REMOVE:
 | 
				
			||||||
 | 
					                    type = PiPipeconfDeviceMappingEvent.Type.REMOVED;
 | 
				
			||||||
 | 
					                    pipeconfToDevices.computeIfPresent(pipeconfId, (pipeconf, devices) -> {
 | 
				
			||||||
 | 
					                        devices.remove(deviceId);
 | 
				
			||||||
 | 
					                        return devices;
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    throw new IllegalArgumentException("Wrong event type " + mapEvent.type());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            notifyDelegate(new PiPipeconfDeviceMappingEvent(type, deviceId));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								core/store/dist/src/main/java/org/onosproject/store/pi/impl/package-info.java
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								core/store/dist/src/main/java/org/onosproject/store/pi/impl/package-info.java
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017-present Open Networking Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Implementation of distributed Pipeconf to device mapping store.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package org.onosproject.store.pi.impl;
 | 
				
			||||||
@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017-present Open Networking Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.store.pi.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.collect.ImmutableSet;
 | 
				
			||||||
 | 
					import org.junit.Before;
 | 
				
			||||||
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					import org.onosproject.net.DeviceId;
 | 
				
			||||||
 | 
					import org.onosproject.net.pi.model.PiPipeconfId;
 | 
				
			||||||
 | 
					import org.onosproject.store.service.TestStorageService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.junit.Assert.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Test class for the Distributed Device to Pipeconf store.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class DistributedDevicePipeconfMappingStoreTest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private DistributedDevicePipeconfMappingStore store;
 | 
				
			||||||
 | 
					    private static final DeviceId DEVICE_ID = DeviceId.deviceId("foo:bar");
 | 
				
			||||||
 | 
					    private static final PiPipeconfId PIPECONF_ID = new PiPipeconfId("foo-pipeconf");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets up the device key store and the storage service test harness.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Before
 | 
				
			||||||
 | 
					    public void setUp() {
 | 
				
			||||||
 | 
					        store = new DistributedDevicePipeconfMappingStore();
 | 
				
			||||||
 | 
					        store.storageService = new TestStorageService();
 | 
				
			||||||
 | 
					        store.setDelegate(event -> {
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        store.activate();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Test for activate.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void activate() {
 | 
				
			||||||
 | 
					        assertNotNull(store.storageService);
 | 
				
			||||||
 | 
					        assertTrue("Store must have delegate", store.hasDelegate());
 | 
				
			||||||
 | 
					        assertTrue("No value should be in the map", store.deviceToPipeconf.isEmpty());
 | 
				
			||||||
 | 
					        assertTrue("No value should be in the map", store.pipeconfToDevices.isEmpty());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Test for deactivate.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void deactivate() {
 | 
				
			||||||
 | 
					        store.deactivate();
 | 
				
			||||||
 | 
					        assertNull("Should be null", store.deviceToPipeconf);
 | 
				
			||||||
 | 
					        assertNull("Should be null", store.pipeconfToDevices);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Test for saving the binding in eventually consistent map and in reverse map.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void createOrUpdatePipeconfToDeviceBinding() {
 | 
				
			||||||
 | 
					        store.createOrUpdateBinding(DEVICE_ID, PIPECONF_ID);
 | 
				
			||||||
 | 
					        assertTrue("Value should be in the map", store.deviceToPipeconf.containsKey(DEVICE_ID));
 | 
				
			||||||
 | 
					        assertTrue("Value should be in the map", store.deviceToPipeconf.containsValue(PIPECONF_ID));
 | 
				
			||||||
 | 
					        assertTrue("Value should be in the map", store.pipeconfToDevices.containsKey(PIPECONF_ID));
 | 
				
			||||||
 | 
					        assertTrue("Value should be in the map", store.pipeconfToDevices.containsValue(ImmutableSet.of(DEVICE_ID)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Test for getting the deviceId to pipeconfId binding.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void getPipeconfIdDevice() throws Exception {
 | 
				
			||||||
 | 
					        clear();
 | 
				
			||||||
 | 
					        createOrUpdatePipeconfToDeviceBinding();
 | 
				
			||||||
 | 
					        assertEquals("Wrong PipeconfId", store.getPipeconfId(DEVICE_ID), PIPECONF_ID);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Test for getting the pipeconfId to devices binding.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void getDevices() {
 | 
				
			||||||
 | 
					        clear();
 | 
				
			||||||
 | 
					        createOrUpdatePipeconfToDeviceBinding();
 | 
				
			||||||
 | 
					        assertEquals("Wrong set of DeviceIds", store.getDevices(PIPECONF_ID), ImmutableSet.of(DEVICE_ID));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Test for clearing binding for a given device.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void clearDeviceToPipeconfBinding() throws Exception {
 | 
				
			||||||
 | 
					        clear();
 | 
				
			||||||
 | 
					        createOrUpdatePipeconfToDeviceBinding();
 | 
				
			||||||
 | 
					        store.removeBinding(DEVICE_ID);
 | 
				
			||||||
 | 
					        assertFalse("Unexpected DeviceId in the map", store.deviceToPipeconf.containsKey(DEVICE_ID));
 | 
				
			||||||
 | 
					        assertTrue("No value should be in the map", store.pipeconfToDevices.get(PIPECONF_ID).isEmpty());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Clears the store and revers map.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void clear() {
 | 
				
			||||||
 | 
					        store.pipeconfToDevices.clear();
 | 
				
			||||||
 | 
					        store.deviceToPipeconf.clear();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user