blob: 96e9b19813b902b1da6d6439bd0b47f0b324963f [file] [log] [blame]
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -08001/*
2 * Copyright 2015 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 */
16package org.onosproject.net.group.impl;
17
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070024import org.onosproject.net.provider.AbstractListenerProviderRegistry;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080025import org.onosproject.core.ApplicationId;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080026import org.onosproject.net.DeviceId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080027import org.onosproject.net.device.DeviceEvent;
28import org.onosproject.net.device.DeviceListener;
29import org.onosproject.net.device.DeviceService;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080030import org.onosproject.net.group.Group;
31import org.onosproject.net.group.GroupBuckets;
32import org.onosproject.net.group.GroupDescription;
33import org.onosproject.net.group.GroupEvent;
34import org.onosproject.net.group.GroupKey;
35import org.onosproject.net.group.GroupListener;
36import org.onosproject.net.group.GroupOperation;
37import org.onosproject.net.group.GroupOperations;
38import org.onosproject.net.group.GroupProvider;
39import org.onosproject.net.group.GroupProviderRegistry;
40import org.onosproject.net.group.GroupProviderService;
41import org.onosproject.net.group.GroupService;
42import org.onosproject.net.group.GroupStore;
43import org.onosproject.net.group.GroupStore.UpdateType;
44import org.onosproject.net.group.GroupStoreDelegate;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080045import org.onosproject.net.provider.AbstractProviderService;
46import org.slf4j.Logger;
47
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070048import java.util.Collection;
49import java.util.Collections;
50
Changhoon Yoon541ef712015-05-23 17:18:34 +090051import static org.onosproject.security.AppGuard.checkPermission;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070052import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoonb856b812015-08-10 03:47:19 +090053import static org.onosproject.security.AppPermission.Type.*;
54
Changhoon Yoon541ef712015-05-23 17:18:34 +090055
56
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080057/**
58 * Provides implementation of the group service APIs.
59 */
60@Component(immediate = true)
61@Service
62public class GroupManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070063 extends AbstractListenerProviderRegistry<GroupEvent, GroupListener,
64 GroupProvider, GroupProviderService>
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080065 implements GroupService, GroupProviderRegistry {
66
67 private final Logger log = getLogger(getClass());
68
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080069 private final GroupStoreDelegate delegate = new InternalGroupStoreDelegate();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080070 private final DeviceListener deviceListener = new InternalDeviceListener();
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080071
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected GroupStore store;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080076 protected DeviceService deviceService;
77
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080078 @Activate
79 public void activate() {
80 store.setDelegate(delegate);
81 eventDispatcher.addSink(GroupEvent.class, listenerRegistry);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080082 deviceService.addListener(deviceListener);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080083 log.info("Started");
84 }
85
86 @Deactivate
87 public void deactivate() {
88 store.unsetDelegate(delegate);
89 eventDispatcher.removeSink(GroupEvent.class);
90 log.info("Stopped");
91 }
92
93 /**
94 * Create a group in the specified device with the provided parameters.
95 *
96 * @param groupDesc group creation parameters
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080097 */
98 @Override
99 public void addGroup(GroupDescription groupDesc) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900100 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800101 store.storeGroupDescription(groupDesc);
102 }
103
104 /**
105 * Return a group object associated to an application cookie.
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700106 * <p>
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800107 * NOTE1: The presence of group object in the system does not
108 * guarantee that the "group" is actually created in device.
109 * GROUP_ADDED notification would confirm the creation of
110 * this group in data plane.
111 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700112 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800113 * @param appCookie application cookie to be used for lookup
114 * @return group associated with the application cookie or
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700115 * NULL if Group is not found for the provided cookie
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800116 */
117 @Override
118 public Group getGroup(DeviceId deviceId, GroupKey appCookie) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900119 checkPermission(GROUP_READ);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800120 return store.getGroup(deviceId, appCookie);
121 }
122
123 /**
124 * Append buckets to existing group. The caller can optionally
125 * associate a new cookie during this updation. GROUP_UPDATED or
126 * GROUP_UPDATE_FAILED notifications would be provided along with
127 * cookie depending on the result of the operation on the device.
128 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700129 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800130 * @param oldCookie cookie to be used to retrieve the existing group
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700131 * @param buckets immutable list of group bucket to be added
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800132 * @param newCookie immutable cookie to be used post update operation
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700133 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800134 */
135 @Override
136 public void addBucketsToGroup(DeviceId deviceId,
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700137 GroupKey oldCookie,
138 GroupBuckets buckets,
139 GroupKey newCookie,
140 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900141 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800142 store.updateGroupDescription(deviceId,
143 oldCookie,
144 UpdateType.ADD,
145 buckets,
146 newCookie);
147 }
148
149 /**
150 * Remove buckets from existing group. The caller can optionally
151 * associate a new cookie during this updation. GROUP_UPDATED or
152 * GROUP_UPDATE_FAILED notifications would be provided along with
153 * cookie depending on the result of the operation on the device.
154 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700155 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800156 * @param oldCookie cookie to be used to retrieve the existing group
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700157 * @param buckets immutable list of group bucket to be removed
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800158 * @param newCookie immutable cookie to be used post update operation
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700159 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800160 */
161 @Override
162 public void removeBucketsFromGroup(DeviceId deviceId,
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700163 GroupKey oldCookie,
164 GroupBuckets buckets,
165 GroupKey newCookie,
166 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900167 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800168 store.updateGroupDescription(deviceId,
169 oldCookie,
170 UpdateType.REMOVE,
171 buckets,
172 newCookie);
173 }
174
175 /**
176 * Delete a group associated to an application cookie.
177 * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
178 * provided along with cookie depending on the result of the
179 * operation on the device.
180 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700181 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800182 * @param appCookie application cookie to be used for lookup
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700183 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800184 */
185 @Override
186 public void removeGroup(DeviceId deviceId,
187 GroupKey appCookie,
188 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900189 checkPermission(GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800190 store.deleteGroupDescription(deviceId, appCookie);
191 }
192
193 /**
194 * Retrieve all groups created by an application in the specified device
195 * as seen by current controller instance.
196 *
197 * @param deviceId device identifier
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700198 * @param appId application id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800199 * @return collection of immutable group objects created by the application
200 */
201 @Override
202 public Iterable<Group> getGroups(DeviceId deviceId,
203 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900204 checkPermission(GROUP_READ);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800205 return store.getGroups(deviceId);
206 }
207
Jonathan Hart32600692015-03-09 10:38:40 -0700208 @Override
209 public Iterable<Group> getGroups(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900210 checkPermission(GROUP_READ);
Jonathan Hart32600692015-03-09 10:38:40 -0700211 return store.getGroups(deviceId);
212 }
213
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800214 @Override
215 protected GroupProviderService createProviderService(GroupProvider provider) {
216 return new InternalGroupProviderService(provider);
217 }
218
219 private class InternalGroupStoreDelegate implements GroupStoreDelegate {
220 @Override
221 public void notify(GroupEvent event) {
222 final Group group = event.subject();
223 GroupProvider groupProvider =
224 getProvider(group.deviceId());
225 GroupOperations groupOps = null;
226 switch (event.type()) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700227 case GROUP_ADD_REQUESTED:
228 log.debug("GROUP_ADD_REQUESTED for Group {} on device {}",
229 group.id(), group.deviceId());
230 GroupOperation groupAddOp = GroupOperation.
231 createAddGroupOperation(group.id(),
232 group.type(),
233 group.buckets());
234 groupOps = new GroupOperations(
235 Collections.singletonList(groupAddOp));
236 groupProvider.performGroupOperation(group.deviceId(), groupOps);
237 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800238
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700239 case GROUP_UPDATE_REQUESTED:
240 log.debug("GROUP_UPDATE_REQUESTED for Group {} on device {}",
241 group.id(), group.deviceId());
242 GroupOperation groupModifyOp = GroupOperation.
243 createModifyGroupOperation(group.id(),
244 group.type(),
245 group.buckets());
246 groupOps = new GroupOperations(
247 Collections.singletonList(groupModifyOp));
248 groupProvider.performGroupOperation(group.deviceId(), groupOps);
249 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800250
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700251 case GROUP_REMOVE_REQUESTED:
252 log.debug("GROUP_REMOVE_REQUESTED for Group {} on device {}",
253 group.id(), group.deviceId());
254 GroupOperation groupDeleteOp = GroupOperation.
255 createDeleteGroupOperation(group.id(),
256 group.type());
257 groupOps = new GroupOperations(
258 Collections.singletonList(groupDeleteOp));
259 groupProvider.performGroupOperation(group.deviceId(), groupOps);
260 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800261
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700262 case GROUP_ADDED:
263 case GROUP_UPDATED:
264 case GROUP_REMOVED:
265 case GROUP_ADD_FAILED:
266 case GROUP_UPDATE_FAILED:
267 case GROUP_REMOVE_FAILED:
268 post(event);
269 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800270
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700271 default:
272 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800273 }
274 }
275 }
276
277 private class InternalGroupProviderService
278 extends AbstractProviderService<GroupProvider>
279 implements GroupProviderService {
280
281 protected InternalGroupProviderService(GroupProvider provider) {
282 super(provider);
283 }
284
285 @Override
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700286 public void groupOperationFailed(DeviceId deviceId, GroupOperation operation) {
sangho7ff01812015-02-09 16:21:53 -0800287 store.groupOperationFailed(deviceId, operation);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800288 }
289
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800290 @Override
291 public void pushGroupMetrics(DeviceId deviceId,
292 Collection<Group> groupEntries) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700293 log.trace("Received group metrics from device {}", deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700294 checkValidity();
295 store.pushGroupMetrics(deviceId, groupEntries);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800296 }
297 }
298
299 private class InternalDeviceListener implements DeviceListener {
300
301 @Override
302 public void event(DeviceEvent event) {
303 switch (event.type()) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700304 case DEVICE_REMOVED:
305 case DEVICE_AVAILABILITY_CHANGED:
306 if (!deviceService.isAvailable(event.subject().id())) {
307 log.debug("Device {} became un available; clearing initial audit status",
308 event.type(), event.subject().id());
309 store.deviceInitialAuditCompleted(event.subject().id(), false);
310 }
311 break;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800312
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700313 default:
314 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800315 }
316 }
317 }
318}