FTTH-50245 - Solution for resiliency in VGC during service deletion/deactivation

Change-Id: I171dedc398eb517e0343cf9b1a699b49ee5b116a
diff --git a/internal/pkg/application/application.go b/internal/pkg/application/application.go
index 6fd69b7..3e2f299 100644
--- a/internal/pkg/application/application.go
+++ b/internal/pkg/application/application.go
@@ -415,6 +415,7 @@
 	macPortMap            map[string]string
 	VnetsToDelete         map[string]bool
 	ServicesToDelete      map[string]bool
+	ServicesToDeactivate  map[string]bool
 	PortAlarmProfileCache map[string]map[string]int // [portAlarmID][ThresholdLevelString]ThresholdLevel
 	vendorID              string
 	ServiceByName         sync.Map // [serName]*VoltService
@@ -652,6 +653,7 @@
 	va.VnetsBySvlan = util.NewConcurrentMap()
 	va.VnetsToDelete = make(map[string]bool)
 	va.ServicesToDelete = make(map[string]bool)
+	va.ServicesToDeactivate = make(map[string]bool)
 	va.VoltPortVnetsToDelete = make(map[*VoltPortVnet]bool)
 	go va.Start(context.Background(), TimerCfg{tick: 100 * time.Millisecond}, tickTimer)
 	go va.Start(context.Background(), TimerCfg{tick: time.Duration(GroupExpiryTime) * time.Minute}, pendingPoolTimer)
@@ -2010,12 +2012,38 @@
 
 // TriggerPendingProfileDeleteReq - trigger pending profile delete request
 func (va *VoltApplication) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
+	va.TriggerPendingServiceDeactivateReq(cntx, device)
 	va.TriggerPendingServiceDeleteReq(cntx, device)
 	va.TriggerPendingVpvDeleteReq(cntx, device)
 	va.TriggerPendingVnetDeleteReq(cntx, device)
 	logger.Warnw(ctx, "All Pending Profile Delete triggered for device", log.Fields{"Device": device})
 }
 
+// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
+func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
+	logger.Infow(ctx, "Pending Services to be deactivated", log.Fields{"Count": len(va.ServicesToDeactivate)})
+	for serviceName := range va.ServicesToDeactivate {
+		logger.Infow(ctx, "Trigger Service Deactivate", log.Fields{"Service": serviceName})
+		if vs := va.GetService(serviceName); vs != nil {
+			if vs.Device == device {
+				logger.Warnw(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
+				vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
+				if vpv == nil {
+					logger.Errorw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name, "port": vs.Port, "Vnet": vs.VnetID})
+					continue
+				}
+
+				vpv.DelTrapFlows(cntx)
+				vs.DelHsiaFlows(cntx)
+				vs.WriteToDb(cntx)
+				vpv.ClearServiceCounters(cntx)
+			}
+		} else {
+			logger.Errorw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
+		}
+	}
+}
+
 // TriggerPendingServiceDeleteReq - trigger pending service delete request
 func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
 	logger.Warnw(ctx, "Pending Services to be deleted", log.Fields{"Count": len(va.ServicesToDelete)})
diff --git a/internal/pkg/application/service.go b/internal/pkg/application/service.go
index 6da1150..1061e21 100644
--- a/internal/pkg/application/service.go
+++ b/internal/pkg/application/service.go
@@ -114,16 +114,17 @@
 	BwAvailInfo     string
 	//MacLearning  bool
 	//MacAddr      net.HardwareAddr
-	Device           string
-	Ipv4Addr         net.IP
-	Ipv6Addr         net.IP
-	ServiceLock      sync.RWMutex `json:"-"`
-	UsMeterID        uint32
-	DsMeterID        uint32
-	AggDsMeterID     uint32
-	UpdateInProgress bool
-	DeleteInProgress bool
-	ForceDelete      bool
+	Device               string
+	Ipv4Addr             net.IP
+	Ipv6Addr             net.IP
+	ServiceLock          sync.RWMutex `json:"-"`
+	UsMeterID            uint32
+	DsMeterID            uint32
+	AggDsMeterID         uint32
+	UpdateInProgress     bool
+	DeleteInProgress     bool
+	DeactivateInProgress bool
+	ForceDelete          bool
 	// Multiservice-Fix
 	UsHSIAFlowsApplied bool
 	DsHSIAFlowsApplied bool
@@ -172,6 +173,7 @@
 	vs.UsHSIAFlowsApplied = false
 	vs.DsHSIAFlowsApplied = false
 	vs.DeleteInProgress = false
+	vs.DeactivateInProgress = false
 	//vs.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
 	vs.IsOption82Enabled = cfg.IsOption82Enabled
 	vs.MacAddr = cfg.MacAddr
@@ -1019,6 +1021,7 @@
 		vs.PendingFlows = oper.PendingFlows
 		vs.AssociatedFlows = oper.AssociatedFlows
 		vs.DeleteInProgress = oper.DeleteInProgress
+		vs.DeactivateInProgress = oper.DeactivateInProgress
 		vs.BwAvailInfo = oper.BwAvailInfo
 		vs.Device = oper.Device
 	} else {
@@ -1437,6 +1440,11 @@
 			logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": vvs.Name, "Error": err})
 		}
 
+		if vvs.VoltServiceOper.DeactivateInProgress {
+			va.ServicesToDeactivate[vvs.VoltServiceCfg.Name] = true
+			logger.Warnw(ctx, "Service (restored) to be deactivated", log.Fields{"Service": vvs.Name})
+		}
+
 		if vvs.VoltServiceOper.DeleteInProgress {
 			va.ServicesToDelete[vvs.VoltServiceCfg.Name] = true
 			logger.Warnw(ctx, "Service (restored) to be deleted", log.Fields{"Service": vvs.Name})
@@ -1696,6 +1704,7 @@
 	nvs.PendingFlows = vs.PendingFlows
 	nvs.AssociatedFlows = vs.AssociatedFlows
 	nvs.DeleteInProgress = vs.DeleteInProgress
+	nvs.DeactivateInProgress = vs.DeactivateInProgress
 	nvs.ForceDelete = vs.ForceDelete
 	nvs.BwAvailInfo = vs.BwAvailInfo
 	nvs.UpdateInProgress = vs.UpdateInProgress
@@ -1966,25 +1975,26 @@
 	return json.Marshal(VoltService{
 		VoltServiceCfg: vs.VoltServiceCfg,
 		VoltServiceOper: VoltServiceOper{
-			Device:             vs.VoltServiceOper.Device,
-			Ipv4Addr:           vs.VoltServiceOper.Ipv4Addr,
-			Ipv6Addr:           vs.VoltServiceOper.Ipv6Addr,
-			UsMeterID:          vs.VoltServiceOper.UsMeterID,
-			DsMeterID:          vs.VoltServiceOper.DsMeterID,
-			AggDsMeterID:       vs.VoltServiceOper.AggDsMeterID,
-			UsHSIAFlowsApplied: vs.VoltServiceOper.UsHSIAFlowsApplied,
-			DsHSIAFlowsApplied: vs.VoltServiceOper.DsHSIAFlowsApplied,
-			UsDhcpFlowsApplied: vs.VoltServiceOper.UsDhcpFlowsApplied,
-			DsDhcpFlowsApplied: vs.VoltServiceOper.DsDhcpFlowsApplied,
-			IgmpFlowsApplied:   vs.VoltServiceOper.IgmpFlowsApplied,
-			Icmpv6FlowsApplied: vs.VoltServiceOper.Icmpv6FlowsApplied,
-			PendingFlows:       vs.VoltServiceOper.PendingFlows,
-			AssociatedFlows:    vs.VoltServiceOper.AssociatedFlows,
-			DeleteInProgress:   vs.VoltServiceOper.DeleteInProgress,
-			ForceDelete:        vs.VoltServiceOper.ForceDelete,
-			BwAvailInfo:        vs.VoltServiceOper.BwAvailInfo,
-			UpdateInProgress:   vs.VoltServiceOper.UpdateInProgress,
-			Metadata:           vs.VoltServiceOper.Metadata,
+			Device:               vs.VoltServiceOper.Device,
+			Ipv4Addr:             vs.VoltServiceOper.Ipv4Addr,
+			Ipv6Addr:             vs.VoltServiceOper.Ipv6Addr,
+			UsMeterID:            vs.VoltServiceOper.UsMeterID,
+			DsMeterID:            vs.VoltServiceOper.DsMeterID,
+			AggDsMeterID:         vs.VoltServiceOper.AggDsMeterID,
+			UsHSIAFlowsApplied:   vs.VoltServiceOper.UsHSIAFlowsApplied,
+			DsHSIAFlowsApplied:   vs.VoltServiceOper.DsHSIAFlowsApplied,
+			UsDhcpFlowsApplied:   vs.VoltServiceOper.UsDhcpFlowsApplied,
+			DsDhcpFlowsApplied:   vs.VoltServiceOper.DsDhcpFlowsApplied,
+			IgmpFlowsApplied:     vs.VoltServiceOper.IgmpFlowsApplied,
+			Icmpv6FlowsApplied:   vs.VoltServiceOper.Icmpv6FlowsApplied,
+			PendingFlows:         vs.VoltServiceOper.PendingFlows,
+			AssociatedFlows:      vs.VoltServiceOper.AssociatedFlows,
+			DeleteInProgress:     vs.VoltServiceOper.DeleteInProgress,
+			DeactivateInProgress: vs.VoltServiceOper.DeactivateInProgress,
+			ForceDelete:          vs.VoltServiceOper.ForceDelete,
+			BwAvailInfo:          vs.VoltServiceOper.BwAvailInfo,
+			UpdateInProgress:     vs.VoltServiceOper.UpdateInProgress,
+			Metadata:             vs.VoltServiceOper.Metadata,
 		},
 	})
 }
@@ -2073,6 +2083,7 @@
 		}
 		if portNo == vs.Port && vs.IsActivated {
 			vs.IsActivated = false
+			vs.DeactivateInProgress = true
 			va.ServiceByName.Store(vs.Name, vs)
 			vs.WriteToDb(cntx)
 			device, err := va.GetDeviceFromPort(portNo)
@@ -2090,6 +2101,7 @@
 					if vpv.IgmpEnabled {
 						va.ReceiverDownInd(cntx, deviceID, portNo)
 					}
+					vs.DeactivateInProgress = false
 				} else {
 					logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
 				}