VOL-3111 Group removal support by VOLTHA Core

Change-Id: Ifb3a7cf62d1f71faec32c3048bad1a0fc3fea2dd
diff --git a/VERSION b/VERSION
index 69fa968..9080d9c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.5.0-dev
+2.5.1-dev
diff --git a/rw_core/core/device/logical_agent_group.go b/rw_core/core/device/logical_agent_group.go
index bf31bc9..10d14b7 100644
--- a/rw_core/core/device/logical_agent_group.go
+++ b/rw_core/core/device/logical_agent_group.go
@@ -99,14 +99,13 @@
 }
 
 func (agent *LogicalAgent) groupDelete(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
-	logger.Debug(ctx, "groupDelete")
+	logger.Debugw(ctx, "groupDelete", log.Fields{"groupMod": groupMod})
 	if groupMod == nil {
 		return nil
 	}
 
 	affectedFlows := make(map[uint64]*ofp.OfpFlowStats)
 	affectedGroups := make(map[uint32]*ofp.OfpGroupEntry)
-	var groupsChanged bool
 
 	toDelete := map[uint32]struct{}{groupMod.GroupId: {}}
 	if groupMod.GroupId == uint32(ofp.OfpGroup_OFPG_ALL) {
@@ -134,27 +133,43 @@
 			}
 		}
 	}
-	groupsChanged = true
 
-	//TODO: groupsChanged is always true here?  use `len(affectedFlows)!=0` or `len(affectedGroups)!=0` instead?
-	if groupsChanged {
-		deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, affectedFlows, affectedGroups)
+	if len(affectedGroups) == 0 {
+		logger.Debugw(ctx, "no-group-to-delete", log.Fields{"groupId": groupMod.GroupId})
+		return nil
+	}
+
+	var deviceRules *fu.DeviceRules
+	var err error
+
+	if len(affectedFlows) != 0 {
+		deviceRules, err = agent.flowDecomposer.DecomposeRules(ctx, agent, affectedFlows, affectedGroups)
 		if err != nil {
 			return err
 		}
-		logger.Debugw(ctx, "rules", log.Fields{"rules": deviceRules.String()})
-
-		// Update the devices
-		respChnls := agent.updateFlowsAndGroupsOfDevice(ctx, deviceRules, nil)
-
-		// Wait for completion
-		go func() {
-			if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
-				logger.Warnw(ctx, "failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
-				//TODO: Revert flow changes
-			}
-		}()
+	} else {
+		//no flow is affected, just remove the groups
+		deviceRules = fu.NewDeviceRules()
+		deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
 	}
+	//add groups to deviceRules
+	for _, groupEntry := range affectedGroups {
+		fg := fu.NewFlowsAndGroups()
+		fg.AddGroup(groupEntry)
+		deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
+	}
+	logger.Debugw(ctx, "rules", log.Fields{"rules": deviceRules.String()})
+
+	// delete groups and related flows, if any
+	respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &voltha.FlowMetadata{}, &ofp.OfpFlowMod{})
+
+	// Wait for completion
+	go func() {
+		if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
+			logger.Warnw(ctx, "failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
+			//TODO: Revert flow changes
+		}
+	}()
 	return nil
 }