1 package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.EnumSet;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.List;
12 import java.util.Map.Entry;
14 import java.util.concurrent.ConcurrentHashMap;
15 import java.util.concurrent.ConcurrentMap;
17 import org.opendaylight.controller.clustering.services.CacheConfigException;
18 import org.opendaylight.controller.clustering.services.CacheExistException;
19 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
20 import org.opendaylight.controller.clustering.services.IClusterServices;
21 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
22 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
24 import org.opendaylight.controller.sal.common.util.Rpcs;
25 import org.opendaylight.controller.sal.core.IContainer;
26 import org.opendaylight.controller.sal.core.Node;
27 import org.opendaylight.controller.sal.utils.GlobalConstants;
28 import org.opendaylight.controller.sal.utils.Status;
29 import org.opendaylight.controller.sal.utils.StatusCode;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
47 import org.opendaylight.yangtools.concepts.Registration;
48 import org.opendaylight.yangtools.yang.binding.DataObject;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.binding.NotificationListener;
51 import org.opendaylight.yangtools.yang.common.RpcError;
52 import org.opendaylight.yangtools.yang.common.RpcResult;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 @SuppressWarnings("unused")
57 public class GroupConsumerImpl {
59 protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
60 private final GroupEventListener groupEventListener = new GroupEventListener();
61 private Registration<NotificationListener> groupListener;
62 private SalGroupService groupService;
63 private GroupDataCommitHandler groupCommitHandler;
65 private IContainer container;
67 public GroupConsumerImpl() {
69 InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Groups.class).toInstance();
70 groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
72 if (null == groupService) {
73 logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended");
74 System.out.println("Consumer SAL Group Service is down or NULL.");
79 groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener);
81 if (null == groupListener) {
82 logger.error("Listener to listen on group data modifcation events");
83 System.out.println("Listener to listen on group data modifcation events.");
87 groupCommitHandler = new GroupDataCommitHandler();
88 FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, groupCommitHandler);
91 public Status validateGroup(Group group) {
93 Iterator<Bucket> bucketIterator;
98 groupName = group.getGroupName();
99 if (!FRMUtil.isNameValid(groupName)) {
100 logger.error("Group Name is invalid %s" + groupName);
101 return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
104 if (!(group.getGroupType().getIntValue() >= GroupTypes.GroupAll.getIntValue() && group.getGroupType()
105 .getIntValue() <= GroupTypes.GroupFf.getIntValue())) {
106 logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
107 return new Status(StatusCode.BADREQUEST, "Invalid Group type");
110 groupBuckets = group.getBuckets();
112 if (null != groupBuckets && null != groupBuckets.getBucket()) {
113 bucketIterator = groupBuckets.getBucket().iterator();
115 while (bucketIterator.hasNext()) {
116 if (!(FRMUtil.validateActions(bucketIterator.next().getAction()))) {
117 logger.error("Error in action bucket");
118 return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents");
124 return new Status(StatusCode.SUCCESS);
128 * Update Group entries to the southbound plugin/inventory and our internal
134 private void updateGroup(InstanceIdentifier<?> path,
135 Group originalGroupDataObject, Group updatedGroupDataObject) {
137 GroupKey groupKey = updatedGroupDataObject.getKey();
138 // Node nodeInstanceID = path.firstIdentifierOf("Node");
139 UpdatedGroupBuilder updateGroupBuilder = null;
140 Status groupOperationStatus = validateGroup(updatedGroupDataObject);
142 if (!groupOperationStatus.isSuccess()) {
143 logger.error("Group data object validation failed %s" + updatedGroupDataObject.getGroupName());
147 UpdateGroupInputBuilder groupInputBuilder = new UpdateGroupInputBuilder();
148 groupInputBuilder.setNode(updatedGroupDataObject.getNode());
149 updateGroupBuilder = new UpdatedGroupBuilder(updatedGroupDataObject);
150 updateGroupBuilder.setGroupId(new GroupId(updatedGroupDataObject.getId()));
151 groupInputBuilder.setUpdatedGroup(updateGroupBuilder.build());
152 OriginalGroupBuilder originalGroupBuilder = new OriginalGroupBuilder(originalGroupDataObject);
153 groupInputBuilder.setOriginalGroup(originalGroupBuilder.build());
154 groupService.updateGroup(groupInputBuilder.build());
159 * Adds Group to the southbound plugin and our internal database
164 private void addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
165 GroupKey groupKey = groupAddDataObject.getKey();
166 Status groupOperationStatus = validateGroup(groupAddDataObject);
168 if (!groupOperationStatus.isSuccess()) {
169 logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
173 AddGroupInputBuilder groupData = new AddGroupInputBuilder();
174 groupData.setBuckets(groupAddDataObject.getBuckets());
175 groupData.setContainerName(groupAddDataObject.getContainerName());
176 groupData.setGroupId(new GroupId(groupAddDataObject.getId()));
177 groupData.setGroupType(groupAddDataObject.getGroupType());
178 groupData.setNode(groupAddDataObject.getNode());
179 groupService.addGroup(groupData.build());
184 * Remove Group to the southbound plugin and our internal database
189 private void removeGroup(InstanceIdentifier<?> path, Group groupRemoveDataObject) {
190 GroupKey groupKey = groupRemoveDataObject.getKey();
191 Status groupOperationStatus = validateGroup(groupRemoveDataObject);
193 if (!groupOperationStatus.isSuccess()) {
194 logger.error("Group data object validation failed %s" + groupRemoveDataObject.getGroupName());
198 RemoveGroupInputBuilder groupData = new RemoveGroupInputBuilder();
199 groupData.setBuckets(groupRemoveDataObject.getBuckets());
200 groupData.setContainerName(groupRemoveDataObject.getContainerName());
201 groupData.setGroupId(new GroupId(groupRemoveDataObject.getId()));
202 groupData.setGroupType(groupRemoveDataObject.getGroupType());
203 groupData.setNode(groupRemoveDataObject.getNode());
204 groupService.removeGroup(groupData.build());
208 private RpcResult<Void> commitToPlugin(InternalTransaction transaction) {
209 DataModification<InstanceIdentifier<?>, DataObject> modification = transaction.modification;
210 //get created entries
211 Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
212 modification.getCreatedConfigurationData().entrySet();
214 //get updated entries
215 Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries =
216 new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
218 updatedEntries.addAll(modification.getUpdatedConfigurationData().entrySet());
219 updatedEntries.removeAll(createdEntries);
221 //get removed entries
222 Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
223 modification.getRemovedConfigurationData();
225 for (Entry<InstanceIdentifier<? extends DataObject >, DataObject> entry : createdEntries) {
226 if(entry.getValue() instanceof Group) {
227 addGroup(entry.getKey(), (Group)entry.getValue());
231 for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
232 if(entry.getValue() instanceof Group) {
233 Group originalGroup = (Group) modification.getOriginalConfigurationData().get(entry.getKey());
234 Group updatedGroup = (Group) entry.getValue();
235 updateGroup(entry.getKey(), originalGroup, updatedGroup);
239 for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
240 DataObject removeValue = modification.getOriginalConfigurationData().get(instanceId);
241 if(removeValue instanceof Group) {
242 removeGroup(instanceId, (Group)removeValue);
246 return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
249 private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
252 public DataCommitTransaction<InstanceIdentifier<?>, DataObject> requestCommit(
253 DataModification<InstanceIdentifier<?>, DataObject> modification) {
254 InternalTransaction transaction = new InternalTransaction(modification);
255 transaction.prepareUpdate();
260 private final class InternalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
262 private final DataModification<InstanceIdentifier<?>, DataObject> modification;
264 public InternalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
265 this.modification = modification;
269 * We create a plan which flows will be added, which will be updated and
270 * which will be removed based on our internal state.
273 void prepareUpdate() {
278 * We are OK to go with execution of plan
282 public RpcResult<Void> finish() throws IllegalStateException {
284 RpcResult<Void> rpcStatus = commitToPlugin(this);
290 * We should rollback our preparation
294 public RpcResult<Void> rollback() throws IllegalStateException {
296 ///needs to be implemented as per gerrit 3314
297 return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
301 public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
307 final class GroupEventListener implements SalGroupListener {
309 List<GroupAdded> addedGroups = new ArrayList<>();
310 List<GroupRemoved> removedGroups = new ArrayList<>();
311 List<GroupUpdated> updatedGroups = new ArrayList<>();
314 public void onGroupAdded(GroupAdded notification) {
315 addedGroups.add(notification);
319 public void onGroupRemoved(GroupRemoved notification) {
320 // TODO Auto-generated method stub
325 public void onGroupUpdated(GroupUpdated notification) {
326 // TODO Auto-generated method stub