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 updatedGroupDataObject, Group originalGroupDataObject) {
136 UpdatedGroupBuilder updateGroupBuilder = null;
137 Status groupOperationStatus = validateGroup(updatedGroupDataObject);
139 if (!groupOperationStatus.isSuccess()) {
140 logger.error("Group data object validation failed %s" + updatedGroupDataObject.getGroupName());
144 UpdateGroupInputBuilder groupInputBuilder = new UpdateGroupInputBuilder();
145 updateGroupBuilder = new UpdatedGroupBuilder(updatedGroupDataObject);
146 updateGroupBuilder.setGroupId(new GroupId(updatedGroupDataObject.getId()));
147 groupInputBuilder.setNode(updatedGroupDataObject.getNode());
148 groupInputBuilder.setUpdatedGroup(updateGroupBuilder.build());
149 OriginalGroupBuilder originalGroupBuilder = new OriginalGroupBuilder(originalGroupDataObject);
150 groupInputBuilder.setOriginalGroup(originalGroupBuilder.build());
151 groupService.updateGroup(groupInputBuilder.build());
156 * Adds Group to the southbound plugin and our internal database
161 private void addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
162 GroupKey groupKey = groupAddDataObject.getKey();
163 Status groupOperationStatus = validateGroup(groupAddDataObject);
165 if (!groupOperationStatus.isSuccess()) {
166 logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
170 AddGroupInputBuilder groupData = new AddGroupInputBuilder();
171 groupData.fieldsFrom(groupAddDataObject);
172 groupData.setGroupId(new GroupId(groupAddDataObject.getId()));
173 groupData.setNode(groupAddDataObject.getNode());
174 groupService.addGroup(groupData.build());
179 * Remove Group to the southbound plugin and our internal database
184 private void removeGroup(InstanceIdentifier<?> path, Group groupRemoveDataObject) {
185 GroupKey groupKey = groupRemoveDataObject.getKey();
186 Status groupOperationStatus = validateGroup(groupRemoveDataObject);
188 if (!groupOperationStatus.isSuccess()) {
189 logger.error("Group data object validation failed %s" + groupRemoveDataObject.getGroupName());
193 RemoveGroupInputBuilder groupData = new RemoveGroupInputBuilder();
194 groupData.fieldsFrom(groupRemoveDataObject);
195 groupData.setGroupId(new GroupId(groupRemoveDataObject.getId()));
196 groupData.setNode(groupRemoveDataObject.getNode());
197 groupService.removeGroup(groupData.build());
201 private RpcResult<Void> commitToPlugin(InternalTransaction transaction) {
202 DataModification<InstanceIdentifier<?>, DataObject> modification = transaction.modification;
203 //get created entries
204 Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
205 modification.getCreatedConfigurationData().entrySet();
207 //get updated entries
208 Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries =
209 new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
211 updatedEntries.addAll(modification.getUpdatedConfigurationData().entrySet());
212 updatedEntries.removeAll(createdEntries);
214 //get removed entries
215 Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
216 modification.getRemovedConfigurationData();
218 for (Entry<InstanceIdentifier<? extends DataObject >, DataObject> entry : createdEntries) {
219 if(entry.getValue() instanceof Group) {
220 addGroup(entry.getKey(), (Group)entry.getValue());
224 for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
225 if(entry.getValue() instanceof Group) {
226 Group originalGroup = (Group) modification.getOriginalConfigurationData().get(entry.getKey());
227 Group updatedGroup = (Group) entry.getValue();
228 updateGroup(entry.getKey(), originalGroup, updatedGroup);
232 for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
233 DataObject removeValue = modification.getOriginalConfigurationData().get(instanceId);
234 if(removeValue instanceof Group) {
235 removeGroup(instanceId, (Group)removeValue);
239 return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
242 private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
245 public DataCommitTransaction<InstanceIdentifier<?>, DataObject> requestCommit(
246 DataModification<InstanceIdentifier<?>, DataObject> modification) {
247 InternalTransaction transaction = new InternalTransaction(modification);
248 transaction.prepareUpdate();
253 private final class InternalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
255 private final DataModification<InstanceIdentifier<?>, DataObject> modification;
257 public InternalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
258 this.modification = modification;
262 * We create a plan which flows will be added, which will be updated and
263 * which will be removed based on our internal state.
266 void prepareUpdate() {
271 * We are OK to go with execution of plan
275 public RpcResult<Void> finish() throws IllegalStateException {
277 RpcResult<Void> rpcStatus = commitToPlugin(this);
283 * We should rollback our preparation
287 public RpcResult<Void> rollback() throws IllegalStateException {
289 ///needs to be implemented as per gerrit 3314
290 return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
294 public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
300 final class GroupEventListener implements SalGroupListener {
302 List<GroupAdded> addedGroups = new ArrayList<>();
303 List<GroupRemoved> removedGroups = new ArrayList<>();
304 List<GroupUpdated> updatedGroups = new ArrayList<>();
307 public void onGroupAdded(GroupAdded notification) {
308 addedGroups.add(notification);
312 public void onGroupRemoved(GroupRemoved notification) {
313 // TODO Auto-generated method stub
318 public void onGroupUpdated(GroupUpdated notification) {
319 // TODO Auto-generated method stub