blob: 352059af5ea36e1f36b9564d545422cfd04fd520 [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 Vavilapalli23181912015-05-04 09:48:09 -070018import static org.slf4j.LoggerFactory.getLogger;
19
20import java.util.Collection;
21import java.util.Collections;
22
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080023import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
28import org.apache.felix.scr.annotations.Service;
29import org.onosproject.core.ApplicationId;
Changhoon Yoon541ef712015-05-23 17:18:34 +090030import org.onosproject.core.Permission;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080031import org.onosproject.event.EventDeliveryService;
Simon Huntff663742015-05-14 13:33:05 -070032import org.onosproject.event.ListenerRegistry;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080033import org.onosproject.net.DeviceId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080034import org.onosproject.net.device.DeviceEvent;
35import org.onosproject.net.device.DeviceListener;
36import org.onosproject.net.device.DeviceService;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080037import org.onosproject.net.group.Group;
38import org.onosproject.net.group.GroupBuckets;
39import org.onosproject.net.group.GroupDescription;
40import org.onosproject.net.group.GroupEvent;
41import org.onosproject.net.group.GroupKey;
42import org.onosproject.net.group.GroupListener;
43import org.onosproject.net.group.GroupOperation;
44import org.onosproject.net.group.GroupOperations;
45import org.onosproject.net.group.GroupProvider;
46import org.onosproject.net.group.GroupProviderRegistry;
47import org.onosproject.net.group.GroupProviderService;
48import org.onosproject.net.group.GroupService;
49import org.onosproject.net.group.GroupStore;
50import org.onosproject.net.group.GroupStore.UpdateType;
51import org.onosproject.net.group.GroupStoreDelegate;
52import org.onosproject.net.provider.AbstractProviderRegistry;
53import org.onosproject.net.provider.AbstractProviderService;
54import org.slf4j.Logger;
55
Changhoon Yoon541ef712015-05-23 17:18:34 +090056import static org.onosproject.security.AppGuard.checkPermission;
57
58
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080059/**
60 * Provides implementation of the group service APIs.
61 */
62@Component(immediate = true)
63@Service
64public class GroupManager
65 extends AbstractProviderRegistry<GroupProvider, GroupProviderService>
66 implements GroupService, GroupProviderRegistry {
67
68 private final Logger log = getLogger(getClass());
69
Simon Huntff663742015-05-14 13:33:05 -070070 private final ListenerRegistry<GroupEvent, GroupListener>
71 listenerRegistry = new ListenerRegistry<>();
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080072 private final GroupStoreDelegate delegate = new InternalGroupStoreDelegate();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080073 private final DeviceListener deviceListener = new InternalDeviceListener();
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080074
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected GroupStore store;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080079 protected DeviceService deviceService;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080082 protected EventDeliveryService eventDispatcher;
83
84 @Activate
85 public void activate() {
86 store.setDelegate(delegate);
87 eventDispatcher.addSink(GroupEvent.class, listenerRegistry);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080088 deviceService.addListener(deviceListener);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080089 log.info("Started");
90 }
91
92 @Deactivate
93 public void deactivate() {
94 store.unsetDelegate(delegate);
95 eventDispatcher.removeSink(GroupEvent.class);
96 log.info("Stopped");
97 }
98
99 /**
100 * Create a group in the specified device with the provided parameters.
101 *
102 * @param groupDesc group creation parameters
103 *
104 */
105 @Override
106 public void addGroup(GroupDescription groupDesc) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900107 checkPermission(Permission.GROUP_WRITE);
108
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700109 log.trace("In addGroup API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800110 store.storeGroupDescription(groupDesc);
111 }
112
113 /**
114 * Return a group object associated to an application cookie.
115 *
116 * NOTE1: The presence of group object in the system does not
117 * guarantee that the "group" is actually created in device.
118 * GROUP_ADDED notification would confirm the creation of
119 * this group in data plane.
120 *
121 * @param deviceId device identifier
122 * @param appCookie application cookie to be used for lookup
123 * @return group associated with the application cookie or
124 * NULL if Group is not found for the provided cookie
125 */
126 @Override
127 public Group getGroup(DeviceId deviceId, GroupKey appCookie) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900128 checkPermission(Permission.GROUP_READ);
129
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700130 log.trace("In getGroup API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800131 return store.getGroup(deviceId, appCookie);
132 }
133
134 /**
135 * Append buckets to existing group. The caller can optionally
136 * associate a new cookie during this updation. GROUP_UPDATED or
137 * GROUP_UPDATE_FAILED notifications would be provided along with
138 * cookie depending on the result of the operation on the device.
139 *
140 * @param deviceId device identifier
141 * @param oldCookie cookie to be used to retrieve the existing group
142 * @param buckets immutable list of group bucket to be added
143 * @param newCookie immutable cookie to be used post update operation
144 * @param appId Application Id
145 */
146 @Override
147 public void addBucketsToGroup(DeviceId deviceId,
148 GroupKey oldCookie,
149 GroupBuckets buckets,
150 GroupKey newCookie,
151 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900152 checkPermission(Permission.GROUP_WRITE);
153
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700154 log.trace("In addBucketsToGroup API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800155 store.updateGroupDescription(deviceId,
156 oldCookie,
157 UpdateType.ADD,
158 buckets,
159 newCookie);
160 }
161
162 /**
163 * Remove buckets from existing group. The caller can optionally
164 * associate a new cookie during this updation. GROUP_UPDATED or
165 * GROUP_UPDATE_FAILED notifications would be provided along with
166 * cookie depending on the result of the operation on the device.
167 *
168 * @param deviceId device identifier
169 * @param oldCookie cookie to be used to retrieve the existing group
170 * @param buckets immutable list of group bucket to be removed
171 * @param newCookie immutable cookie to be used post update operation
172 * @param appId Application Id
173 */
174 @Override
175 public void removeBucketsFromGroup(DeviceId deviceId,
176 GroupKey oldCookie,
177 GroupBuckets buckets,
178 GroupKey newCookie,
179 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900180 checkPermission(Permission.GROUP_WRITE);
181
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700182 log.trace("In removeBucketsFromGroup API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800183 store.updateGroupDescription(deviceId,
184 oldCookie,
185 UpdateType.REMOVE,
186 buckets,
187 newCookie);
188 }
189
190 /**
191 * Delete a group associated to an application cookie.
192 * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
193 * provided along with cookie depending on the result of the
194 * operation on the device.
195 *
196 * @param deviceId device identifier
197 * @param appCookie application cookie to be used for lookup
198 * @param appId Application Id
199 */
200 @Override
201 public void removeGroup(DeviceId deviceId,
202 GroupKey appCookie,
203 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900204 checkPermission(Permission.GROUP_WRITE);
205
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700206 log.trace("In removeGroup API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800207 store.deleteGroupDescription(deviceId, appCookie);
208 }
209
210 /**
211 * Retrieve all groups created by an application in the specified device
212 * as seen by current controller instance.
213 *
214 * @param deviceId device identifier
215 * @param appId application id
216 * @return collection of immutable group objects created by the application
217 */
218 @Override
219 public Iterable<Group> getGroups(DeviceId deviceId,
220 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900221 checkPermission(Permission.GROUP_READ);
222
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700223 log.trace("In getGroups API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800224 return store.getGroups(deviceId);
225 }
226
Jonathan Hart32600692015-03-09 10:38:40 -0700227 @Override
228 public Iterable<Group> getGroups(DeviceId deviceId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900229 checkPermission(Permission.GROUP_READ);
230
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700231 log.trace("In getGroups API");
Jonathan Hart32600692015-03-09 10:38:40 -0700232 return store.getGroups(deviceId);
233 }
234
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800235 /**
236 * Adds the specified group listener.
237 *
238 * @param listener group listener
239 */
240 @Override
241 public void addListener(GroupListener listener) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900242 checkPermission(Permission.GROUP_EVENT);
243
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700244 log.trace("In addListener API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800245 listenerRegistry.addListener(listener);
246 }
247
248 /**
249 * Removes the specified group listener.
250 *
251 * @param listener group listener
252 */
253 @Override
254 public void removeListener(GroupListener listener) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900255 checkPermission(Permission.GROUP_EVENT);
256
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700257 log.trace("In removeListener API");
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800258 listenerRegistry.removeListener(listener);
259 }
260
261 @Override
262 protected GroupProviderService createProviderService(GroupProvider provider) {
263 return new InternalGroupProviderService(provider);
264 }
265
266 private class InternalGroupStoreDelegate implements GroupStoreDelegate {
267 @Override
268 public void notify(GroupEvent event) {
269 final Group group = event.subject();
270 GroupProvider groupProvider =
271 getProvider(group.deviceId());
272 GroupOperations groupOps = null;
273 switch (event.type()) {
274 case GROUP_ADD_REQUESTED:
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800275 log.debug("GROUP_ADD_REQUESTED for Group {} on device {}",
276 group.id(), group.deviceId());
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800277 GroupOperation groupAddOp = GroupOperation.
278 createAddGroupOperation(group.id(),
279 group.type(),
280 group.buckets());
281 groupOps = new GroupOperations(
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700282 Collections.singletonList(groupAddOp));
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800283 groupProvider.performGroupOperation(group.deviceId(), groupOps);
284 break;
285
286 case GROUP_UPDATE_REQUESTED:
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800287 log.debug("GROUP_UPDATE_REQUESTED for Group {} on device {}",
288 group.id(), group.deviceId());
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800289 GroupOperation groupModifyOp = GroupOperation.
290 createModifyGroupOperation(group.id(),
291 group.type(),
292 group.buckets());
293 groupOps = new GroupOperations(
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700294 Collections.singletonList(groupModifyOp));
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800295 groupProvider.performGroupOperation(group.deviceId(), groupOps);
296 break;
297
298 case GROUP_REMOVE_REQUESTED:
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800299 log.debug("GROUP_REMOVE_REQUESTED for Group {} on device {}",
300 group.id(), group.deviceId());
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800301 GroupOperation groupDeleteOp = GroupOperation.
302 createDeleteGroupOperation(group.id(),
303 group.type());
304 groupOps = new GroupOperations(
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700305 Collections.singletonList(groupDeleteOp));
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800306 groupProvider.performGroupOperation(group.deviceId(), groupOps);
307 break;
308
309 case GROUP_ADDED:
310 case GROUP_UPDATED:
311 case GROUP_REMOVED:
sangho7ff01812015-02-09 16:21:53 -0800312 case GROUP_ADD_FAILED:
313 case GROUP_UPDATE_FAILED:
314 case GROUP_REMOVE_FAILED:
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800315 eventDispatcher.post(event);
316 break;
317
318 default:
319 break;
320 }
321 }
322 }
323
324 private class InternalGroupProviderService
325 extends AbstractProviderService<GroupProvider>
326 implements GroupProviderService {
327
328 protected InternalGroupProviderService(GroupProvider provider) {
329 super(provider);
330 }
331
332 @Override
sangho7ff01812015-02-09 16:21:53 -0800333 public void groupOperationFailed(DeviceId deviceId,
334 GroupOperation operation) {
335 store.groupOperationFailed(deviceId, operation);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800336 }
337
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800338 @Override
339 public void pushGroupMetrics(DeviceId deviceId,
340 Collection<Group> groupEntries) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800341 log.trace("Received group metrics from device {}",
342 deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700343 checkValidity();
344 store.pushGroupMetrics(deviceId, groupEntries);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800345 }
346 }
347
348 private class InternalDeviceListener implements DeviceListener {
349
350 @Override
351 public void event(DeviceEvent event) {
352 switch (event.type()) {
353 case DEVICE_REMOVED:
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700354 case DEVICE_AVAILABILITY_CHANGED:
355 if (!deviceService.isAvailable(event.subject().id())) {
356 log.debug("GroupService DeviceListener: Received event {}."
357 + "Device is no more available."
358 + "Clearing device {} initial "
359 + "AUDIT completed status",
360 event.type(),
361 event.subject().id());
362 store.deviceInitialAuditCompleted(event.subject().id(), false);
363 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800364 break;
365
366 default:
367 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800368 }
369 }
370 }
371}