| /* |
| * Copyright 2017-present 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.incubator.net.virtual.impl; |
| |
| import org.onosproject.core.ApplicationId; |
| import org.onosproject.incubator.net.virtual.NetworkId; |
| import org.onosproject.incubator.net.virtual.VirtualNetworkGroupStore; |
| import org.onosproject.incubator.net.virtual.VirtualNetworkService; |
| import org.onosproject.incubator.net.virtual.event.AbstractVirtualListenerManager; |
| import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProviderService; |
| import org.onosproject.incubator.net.virtual.provider.VirtualGroupProvider; |
| import org.onosproject.incubator.net.virtual.provider.VirtualGroupProviderService; |
| import org.onosproject.incubator.net.virtual.provider.VirtualProviderRegistryService; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.device.DeviceEvent; |
| import org.onosproject.net.device.DeviceListener; |
| import org.onosproject.net.device.DeviceService; |
| import org.onosproject.net.group.Group; |
| import org.onosproject.net.group.GroupBuckets; |
| import org.onosproject.net.group.GroupDescription; |
| import org.onosproject.net.group.GroupEvent; |
| import org.onosproject.net.group.GroupKey; |
| import org.onosproject.net.group.GroupListener; |
| import org.onosproject.net.group.GroupOperation; |
| import org.onosproject.net.group.GroupOperations; |
| import org.onosproject.net.group.GroupService; |
| import org.onosproject.net.group.GroupStoreDelegate; |
| import org.onosproject.net.provider.ProviderId; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Set; |
| |
| /** |
| * Group service implementation built on the virtual network service. |
| */ |
| public class VirtualNetworkGroupManager |
| extends AbstractVirtualListenerManager<GroupEvent, GroupListener> |
| implements GroupService { |
| |
| private final Logger log = LoggerFactory.getLogger(getClass()); |
| |
| private final VirtualNetworkGroupStore store; |
| |
| private VirtualProviderRegistryService providerRegistryService = null; |
| private VirtualGroupProviderService innerProviderService; |
| private InternalStoreDelegate storeDelegate; |
| private DeviceService deviceService; |
| |
| //TODO: make this configurable |
| private boolean purgeOnDisconnection = false; |
| |
| public VirtualNetworkGroupManager(VirtualNetworkService manager, NetworkId networkId) { |
| super(manager, networkId, GroupEvent.class); |
| |
| store = serviceDirectory.get(VirtualNetworkGroupStore.class); |
| deviceService = manager.get(networkId, DeviceService.class); |
| |
| providerRegistryService = |
| serviceDirectory.get(VirtualProviderRegistryService.class); |
| innerProviderService = new InternalGroupProviderService(); |
| providerRegistryService.registerProviderService(networkId(), innerProviderService); |
| |
| this.storeDelegate = new InternalStoreDelegate(); |
| store.setDelegate(networkId, this.storeDelegate); |
| |
| log.info("Started"); |
| } |
| |
| @Override |
| public void addGroup(GroupDescription groupDesc) { |
| store.storeGroupDescription(networkId(), groupDesc); |
| } |
| |
| @Override |
| public Group getGroup(DeviceId deviceId, GroupKey appCookie) { |
| return store.getGroup(networkId(), deviceId, appCookie); |
| } |
| |
| @Override |
| public void addBucketsToGroup(DeviceId deviceId, GroupKey oldCookie, GroupBuckets buckets, |
| GroupKey newCookie, ApplicationId appId) { |
| store.updateGroupDescription(networkId(), |
| deviceId, |
| oldCookie, |
| VirtualNetworkGroupStore.UpdateType.ADD, |
| buckets, |
| newCookie); |
| } |
| |
| @Override |
| public void removeBucketsFromGroup(DeviceId deviceId, GroupKey oldCookie, |
| GroupBuckets buckets, GroupKey newCookie, |
| ApplicationId appId) { |
| store.updateGroupDescription(networkId(), |
| deviceId, |
| oldCookie, |
| VirtualNetworkGroupStore.UpdateType.REMOVE, |
| buckets, |
| newCookie); |
| |
| } |
| |
| @Override |
| public void setBucketsForGroup(DeviceId deviceId, |
| GroupKey oldCookie, |
| GroupBuckets buckets, |
| GroupKey newCookie, |
| ApplicationId appId) { |
| store.updateGroupDescription(networkId(), |
| deviceId, |
| oldCookie, |
| VirtualNetworkGroupStore.UpdateType.SET, |
| buckets, |
| newCookie); |
| } |
| |
| @Override |
| public void purgeGroupEntries(DeviceId deviceId) { |
| store.purgeGroupEntry(networkId(), deviceId); |
| } |
| |
| @Override |
| public void purgeGroupEntries() { |
| store.purgeGroupEntries(networkId()); |
| } |
| |
| @Override |
| public void removeGroup(DeviceId deviceId, GroupKey appCookie, ApplicationId appId) { |
| store.deleteGroupDescription(networkId(), deviceId, appCookie); |
| } |
| |
| @Override |
| public Iterable<Group> getGroups(DeviceId deviceId, ApplicationId appId) { |
| return store.getGroups(networkId(), deviceId); |
| } |
| |
| @Override |
| public Iterable<Group> getGroups(DeviceId deviceId) { |
| return store.getGroups(networkId(), deviceId); |
| } |
| |
| private class InternalGroupProviderService |
| extends AbstractVirtualProviderService<VirtualGroupProvider> |
| implements VirtualGroupProviderService { |
| |
| protected InternalGroupProviderService() { |
| Set<ProviderId> providerIds = |
| providerRegistryService.getProvidersByService(this); |
| ProviderId providerId = providerIds.stream().findFirst().get(); |
| VirtualGroupProvider provider = (VirtualGroupProvider) |
| providerRegistryService.getProvider(providerId); |
| setProvider(provider); |
| } |
| |
| @Override |
| public void groupOperationFailed(DeviceId deviceId, |
| GroupOperation operation) { |
| store.groupOperationFailed(networkId(), deviceId, operation); |
| } |
| |
| @Override |
| public void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries) { |
| log.trace("Received group metrics from device {}", deviceId); |
| checkValidity(); |
| store.pushGroupMetrics(networkId(), deviceId, groupEntries); |
| } |
| |
| @Override |
| public void notifyOfFailovers(Collection<Group> failoverGroups) { |
| store.notifyOfFailovers(networkId(), failoverGroups); |
| } |
| } |
| |
| private class InternalStoreDelegate implements GroupStoreDelegate { |
| @Override |
| public void notify(GroupEvent event) { |
| final Group group = event.subject(); |
| VirtualGroupProvider groupProvider = innerProviderService.provider(); |
| GroupOperations groupOps = null; |
| switch (event.type()) { |
| case GROUP_ADD_REQUESTED: |
| log.debug("GROUP_ADD_REQUESTED for Group {} on device {}", |
| group.id(), group.deviceId()); |
| GroupOperation groupAddOp = GroupOperation. |
| createAddGroupOperation(group.id(), |
| group.type(), |
| group.buckets()); |
| groupOps = new GroupOperations( |
| Collections.singletonList(groupAddOp)); |
| groupProvider.performGroupOperation(networkId(), group.deviceId(), |
| groupOps); |
| break; |
| |
| case GROUP_UPDATE_REQUESTED: |
| log.debug("GROUP_UPDATE_REQUESTED for Group {} on device {}", |
| group.id(), group.deviceId()); |
| GroupOperation groupModifyOp = GroupOperation. |
| createModifyGroupOperation(group.id(), |
| group.type(), |
| group.buckets()); |
| groupOps = new GroupOperations( |
| Collections.singletonList(groupModifyOp)); |
| groupProvider.performGroupOperation(networkId(), group.deviceId(), |
| groupOps); |
| break; |
| |
| case GROUP_REMOVE_REQUESTED: |
| log.debug("GROUP_REMOVE_REQUESTED for Group {} on device {}", |
| group.id(), group.deviceId()); |
| GroupOperation groupDeleteOp = GroupOperation. |
| createDeleteGroupOperation(group.id(), |
| group.type()); |
| groupOps = new GroupOperations( |
| Collections.singletonList(groupDeleteOp)); |
| groupProvider.performGroupOperation(networkId(), group.deviceId(), |
| groupOps); |
| break; |
| |
| case GROUP_ADDED: |
| case GROUP_UPDATED: |
| case GROUP_REMOVED: |
| case GROUP_ADD_FAILED: |
| case GROUP_UPDATE_FAILED: |
| case GROUP_REMOVE_FAILED: |
| case GROUP_BUCKET_FAILOVER: |
| post(event); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| private class InternalDeviceListener implements DeviceListener { |
| @Override |
| public void event(DeviceEvent event) { |
| switch (event.type()) { |
| case DEVICE_REMOVED: |
| case DEVICE_AVAILABILITY_CHANGED: |
| DeviceId deviceId = event.subject().id(); |
| if (!deviceService.isAvailable(deviceId)) { |
| log.debug("Device {} became un available; clearing initial audit status", |
| event.type(), event.subject().id()); |
| store.deviceInitialAuditCompleted(networkId(), event.subject().id(), false); |
| |
| if (purgeOnDisconnection) { |
| store.purgeGroupEntry(networkId(), deviceId); |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| } |