blob: 6c43f2459afe95222b99da825f432f172fd5af9f [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;
Changhoon Yoon541ef712015-05-23 17:18:34 +090026import org.onosproject.core.Permission;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080027import org.onosproject.net.DeviceId;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080028import org.onosproject.net.device.DeviceEvent;
29import org.onosproject.net.device.DeviceListener;
30import org.onosproject.net.device.DeviceService;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080031import org.onosproject.net.group.Group;
32import org.onosproject.net.group.GroupBuckets;
33import org.onosproject.net.group.GroupDescription;
34import org.onosproject.net.group.GroupEvent;
35import org.onosproject.net.group.GroupKey;
36import org.onosproject.net.group.GroupListener;
37import org.onosproject.net.group.GroupOperation;
38import org.onosproject.net.group.GroupOperations;
39import org.onosproject.net.group.GroupProvider;
40import org.onosproject.net.group.GroupProviderRegistry;
41import org.onosproject.net.group.GroupProviderService;
42import org.onosproject.net.group.GroupService;
43import org.onosproject.net.group.GroupStore;
44import org.onosproject.net.group.GroupStore.UpdateType;
45import org.onosproject.net.group.GroupStoreDelegate;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080046import org.onosproject.net.provider.AbstractProviderService;
47import org.slf4j.Logger;
48
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070049import java.util.Collection;
50import java.util.Collections;
51
Changhoon Yoon541ef712015-05-23 17:18:34 +090052import static org.onosproject.security.AppGuard.checkPermission;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070053import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoon541ef712015-05-23 17:18:34 +090054
55
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080056/**
57 * Provides implementation of the group service APIs.
58 */
59@Component(immediate = true)
60@Service
61public class GroupManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070062 extends AbstractListenerProviderRegistry<GroupEvent, GroupListener,
63 GroupProvider, GroupProviderService>
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080064 implements GroupService, GroupProviderRegistry {
65
66 private final Logger log = getLogger(getClass());
67
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080068 private final GroupStoreDelegate delegate = new InternalGroupStoreDelegate();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080069 private final DeviceListener deviceListener = new InternalDeviceListener();
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080070
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected GroupStore store;
73
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080075 protected DeviceService deviceService;
76
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080077 @Activate
78 public void activate() {
79 store.setDelegate(delegate);
80 eventDispatcher.addSink(GroupEvent.class, listenerRegistry);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080081 deviceService.addListener(deviceListener);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080082 log.info("Started");
83 }
84
85 @Deactivate
86 public void deactivate() {
87 store.unsetDelegate(delegate);
88 eventDispatcher.removeSink(GroupEvent.class);
89 log.info("Stopped");
90 }
91
92 /**
93 * Create a group in the specified device with the provided parameters.
94 *
95 * @param groupDesc group creation parameters
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -080096 */
97 @Override
98 public void addGroup(GroupDescription groupDesc) {
Changhoon Yoon541ef712015-05-23 17:18:34 +090099 checkPermission(Permission.GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800100 store.storeGroupDescription(groupDesc);
101 }
102
103 /**
104 * Return a group object associated to an application cookie.
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700105 * <p>
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800106 * NOTE1: The presence of group object in the system does not
107 * guarantee that the "group" is actually created in device.
108 * GROUP_ADDED notification would confirm the creation of
109 * this group in data plane.
110 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700111 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800112 * @param appCookie application cookie to be used for lookup
113 * @return group associated with the application cookie or
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700114 * NULL if Group is not found for the provided cookie
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800115 */
116 @Override
117 public Group getGroup(DeviceId deviceId, GroupKey appCookie) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900118 checkPermission(Permission.GROUP_READ);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800119 return store.getGroup(deviceId, appCookie);
120 }
121
122 /**
123 * Append buckets to existing group. The caller can optionally
124 * associate a new cookie during this updation. GROUP_UPDATED or
125 * GROUP_UPDATE_FAILED notifications would be provided along with
126 * cookie depending on the result of the operation on the device.
127 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700128 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800129 * @param oldCookie cookie to be used to retrieve the existing group
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700130 * @param buckets immutable list of group bucket to be added
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800131 * @param newCookie immutable cookie to be used post update operation
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700132 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800133 */
134 @Override
135 public void addBucketsToGroup(DeviceId deviceId,
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700136 GroupKey oldCookie,
137 GroupBuckets buckets,
138 GroupKey newCookie,
139 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900140 checkPermission(Permission.GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800141 store.updateGroupDescription(deviceId,
142 oldCookie,
143 UpdateType.ADD,
144 buckets,
145 newCookie);
146 }
147
148 /**
149 * Remove buckets from existing group. The caller can optionally
150 * associate a new cookie during this updation. GROUP_UPDATED or
151 * GROUP_UPDATE_FAILED notifications would be provided along with
152 * cookie depending on the result of the operation on the device.
153 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700154 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800155 * @param oldCookie cookie to be used to retrieve the existing group
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700156 * @param buckets immutable list of group bucket to be removed
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800157 * @param newCookie immutable cookie to be used post update operation
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700158 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800159 */
160 @Override
161 public void removeBucketsFromGroup(DeviceId deviceId,
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700162 GroupKey oldCookie,
163 GroupBuckets buckets,
164 GroupKey newCookie,
165 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900166 checkPermission(Permission.GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800167 store.updateGroupDescription(deviceId,
168 oldCookie,
169 UpdateType.REMOVE,
170 buckets,
171 newCookie);
172 }
173
174 /**
175 * Delete a group associated to an application cookie.
176 * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
177 * provided along with cookie depending on the result of the
178 * operation on the device.
179 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700180 * @param deviceId device identifier
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800181 * @param appCookie application cookie to be used for lookup
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700182 * @param appId Application Id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800183 */
184 @Override
185 public void removeGroup(DeviceId deviceId,
186 GroupKey appCookie,
187 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900188 checkPermission(Permission.GROUP_WRITE);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800189 store.deleteGroupDescription(deviceId, appCookie);
190 }
191
192 /**
193 * Retrieve all groups created by an application in the specified device
194 * as seen by current controller instance.
195 *
196 * @param deviceId device identifier
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700197 * @param appId application id
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800198 * @return collection of immutable group objects created by the application
199 */
200 @Override
201 public Iterable<Group> getGroups(DeviceId deviceId,
202 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900203 checkPermission(Permission.GROUP_READ);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800204 return store.getGroups(deviceId);
205 }
206
Jonathan Hart32600692015-03-09 10:38:40 -0700207 @Override
208 public Iterable<Group> getGroups(DeviceId deviceId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900209 checkPermission(Permission.GROUP_READ);
Jonathan Hart32600692015-03-09 10:38:40 -0700210 return store.getGroups(deviceId);
211 }
212
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800213 @Override
214 protected GroupProviderService createProviderService(GroupProvider provider) {
215 return new InternalGroupProviderService(provider);
216 }
217
218 private class InternalGroupStoreDelegate implements GroupStoreDelegate {
219 @Override
220 public void notify(GroupEvent event) {
221 final Group group = event.subject();
222 GroupProvider groupProvider =
223 getProvider(group.deviceId());
224 GroupOperations groupOps = null;
225 switch (event.type()) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700226 case GROUP_ADD_REQUESTED:
227 log.debug("GROUP_ADD_REQUESTED for Group {} on device {}",
228 group.id(), group.deviceId());
229 GroupOperation groupAddOp = GroupOperation.
230 createAddGroupOperation(group.id(),
231 group.type(),
232 group.buckets());
233 groupOps = new GroupOperations(
234 Collections.singletonList(groupAddOp));
235 groupProvider.performGroupOperation(group.deviceId(), groupOps);
236 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800237
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700238 case GROUP_UPDATE_REQUESTED:
239 log.debug("GROUP_UPDATE_REQUESTED for Group {} on device {}",
240 group.id(), group.deviceId());
241 GroupOperation groupModifyOp = GroupOperation.
242 createModifyGroupOperation(group.id(),
243 group.type(),
244 group.buckets());
245 groupOps = new GroupOperations(
246 Collections.singletonList(groupModifyOp));
247 groupProvider.performGroupOperation(group.deviceId(), groupOps);
248 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800249
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700250 case GROUP_REMOVE_REQUESTED:
251 log.debug("GROUP_REMOVE_REQUESTED for Group {} on device {}",
252 group.id(), group.deviceId());
253 GroupOperation groupDeleteOp = GroupOperation.
254 createDeleteGroupOperation(group.id(),
255 group.type());
256 groupOps = new GroupOperations(
257 Collections.singletonList(groupDeleteOp));
258 groupProvider.performGroupOperation(group.deviceId(), groupOps);
259 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800260
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700261 case GROUP_ADDED:
262 case GROUP_UPDATED:
263 case GROUP_REMOVED:
264 case GROUP_ADD_FAILED:
265 case GROUP_UPDATE_FAILED:
266 case GROUP_REMOVE_FAILED:
267 post(event);
268 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800269
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700270 default:
271 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800272 }
273 }
274 }
275
276 private class InternalGroupProviderService
277 extends AbstractProviderService<GroupProvider>
278 implements GroupProviderService {
279
280 protected InternalGroupProviderService(GroupProvider provider) {
281 super(provider);
282 }
283
284 @Override
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700285 public void groupOperationFailed(DeviceId deviceId, GroupOperation operation) {
sangho7ff01812015-02-09 16:21:53 -0800286 store.groupOperationFailed(deviceId, operation);
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800287 }
288
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800289 @Override
290 public void pushGroupMetrics(DeviceId deviceId,
291 Collection<Group> groupEntries) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700292 log.trace("Received group metrics from device {}", deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700293 checkValidity();
294 store.pushGroupMetrics(deviceId, groupEntries);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800295 }
296 }
297
298 private class InternalDeviceListener implements DeviceListener {
299
300 @Override
301 public void event(DeviceEvent event) {
302 switch (event.type()) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700303 case DEVICE_REMOVED:
304 case DEVICE_AVAILABILITY_CHANGED:
305 if (!deviceService.isAvailable(event.subject().id())) {
306 log.debug("Device {} became un available; clearing initial audit status",
307 event.type(), event.subject().id());
308 store.deviceInitialAuditCompleted(event.subject().id(), false);
309 }
310 break;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800311
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700312 default:
313 break;
Srikanth Vavilapalli45c27c82015-01-30 12:57:56 -0800314 }
315 }
316 }
317}