FTTH-52535 [Introduced rest interface to fetch flow frovision status in controller]

Change-Id: I9e9054ab4a02906226fe1691eee4f101413a8ead
diff --git a/internal/pkg/application/service.go b/internal/pkg/application/service.go
index 5d7bc43..ebbeef0 100644
--- a/internal/pkg/application/service.go
+++ b/internal/pkg/application/service.go
@@ -44,6 +44,18 @@
 	DSLAttrEnabled string = "ENABLED"
 	// DeviceAny constant
 	DeviceAny string = "DEVICE-ANY"
+
+	ALL_FLOWS_PROVISIONED string = "ALL_FLOWS_PROVISIONED"
+
+	NO_FLOWS_PROVISIONED string = "NO_FLOWS_PROVISIONED"
+
+	FLOWS_PROVISIONED_PARTIALLY string = "FLOWS_PROVISIONED_PARTIALLY"
+
+	SUBSCRIBER_DISABLED_IN_CONTROLLER string = "DISABLED_IN_CONTROLLER"
+
+	SUBSCRIBER_NOT_IN_CONTROLLER string = "NOT_IN_CONTROLLER"
+
+	ONT_FLOWS_PROVISION_STATE_UNUSED string = "ONT_FLOWS_PROVISION_STATE_UNUSED"
 )
 
 // VoltServiceCfg structure
@@ -2030,6 +2042,49 @@
 	return svcList, nil
 }
 
+type FlowProvisionStatus struct {
+	FlowProvisionStatus string
+}
+
+// GetFlowProvisionStatus to get status of the subscriber and flow provisioned in controller
+func (va *VoltApplication) GetFlowProvisionStatus(cntx context.Context, portNo string) FlowProvisionStatus {
+	logger.Infow(ctx, "GetFlowProvisionStatus Request ", log.Fields{"Port": portNo})
+	flowProvisionStatus := FlowProvisionStatus{}
+	serviceCount := 0
+	va.ServiceByName.Range(func(key, value interface{}) bool {
+		vs := value.(*VoltService)
+		logger.Debugw(ctx, "Volt Service ", log.Fields{"VS": vs})
+		serviceCount++
+		if len(portNo) > 0 {
+			if portNo == vs.Port {
+				if vs.DsHSIAFlowsApplied && vs.UsHSIAFlowsApplied && vs.LenOfPendingFlows() == 0 {
+					flowProvisionStatus.FlowProvisionStatus = ALL_FLOWS_PROVISIONED
+				} else if !vs.IsActivated {
+					flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_DISABLED_IN_CONTROLLER
+				} else if !vs.DsHSIAFlowsApplied && !vs.UsHSIAFlowsApplied {
+					flowProvisionStatus.FlowProvisionStatus = NO_FLOWS_PROVISIONED
+				} else if vs.LenOfPendingFlows() > 0 {
+					flowProvisionStatus.FlowProvisionStatus = FLOWS_PROVISIONED_PARTIALLY
+				}
+			} else {
+				flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_NOT_IN_CONTROLLER
+			}
+		}
+		return true
+	})
+	if serviceCount == 0 {
+		flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_NOT_IN_CONTROLLER
+	}
+	return flowProvisionStatus
+}
+
+func (vs *VoltService) LenOfPendingFlows() int {
+	vs.ServiceLock.RLock()
+	lth := len(vs.PendingFlows)
+	vs.ServiceLock.RUnlock()
+	return lth
+}
+
 // ActivateService to activate pre-provisioned service
 func (va *VoltApplication) ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
 	var isParmsInvalid bool
diff --git a/internal/pkg/vpagent/connection.go b/internal/pkg/vpagent/connection.go
index 21aa569..4c274d4 100644
--- a/internal/pkg/vpagent/connection.go
+++ b/internal/pkg/vpagent/connection.go
@@ -63,7 +63,7 @@
 				}
 			}
 		}
-		logger.Fatalw(ctx, "Failed to connect to voltha",
+		logger.Errorw(ctx, "Failed to connect to voltha",
 			log.Fields{
 				"VolthaApiEndPoint": vpa.VolthaAPIEndPoint,
 				"error":             err.Error(),
diff --git a/voltha-go-controller/nbi/rest.go b/voltha-go-controller/nbi/rest.go
index 6f876e8..9c1fe82 100644
--- a/voltha-go-controller/nbi/rest.go
+++ b/voltha-go-controller/nbi/rest.go
@@ -45,6 +45,7 @@
 	FlowPerDeviceIDFlowIDPath         string = "/flows/{deviceId}/{flowId}"
 	PendingFlowsPath                  string = "/flows/pending"
 	ProgrammedSubscribersPath         string = "/programmed-subscribers"
+	ProgrammedSubscribersByIdPath     string = "/programmed-subscribers/{device}/{port}"
 	ServiceDevicePortPath             string = "/services/{device}/{port}"
 	ServicePortNamePath               string = "/services/{portName}"
 	ServicePortStagCtagTpIDPath       string = "/services/{portName}/{sTag}/{cTag}/{tpId}"
@@ -59,8 +60,9 @@
 	GroupsPath                        string = "/groups"
 	GroupsByIDPath                    string = "/groups/{id}"
 	OltFlowServicePath                string = "/oltflowservice"
-	NetConfigPath                     string = "/network/configurations"
+	NetConfigPath                     string = "/network-configurations"
 	DeviceConfigPath                  string = "/olt/{serialNumber}"
+	FlowProvisionStatus               string = "/flow-status/{portName}"
 )
 
 // RestStart to execute for API
@@ -78,6 +80,7 @@
 	mu.HandleFunc(BasePath+FlowPerDeviceIDFlowIDPath, (&onosnbi.FlowHandle{}).ServeHTTP)
 	mu.HandleFunc(BasePath+PendingFlowsPath, (&onosnbi.PendingFlowHandle{}).ServeHTTP)
 	mu.HandleFunc(BasePath+ProgrammedSubscribersPath, (&onosnbi.ServiceAdapter{}).ServeHTTP)
+	mu.HandleFunc(BasePath+ProgrammedSubscribersByIdPath, (&onosnbi.ServiceAdapter{}).ServeHTTP)
 	mu.HandleFunc(BasePath+ServiceDevicePortPath, (&onosnbi.ServiceAdapter{}).ServeHTTP)
 	mu.HandleFunc(BasePath+ServicePortNamePath, (&onosnbi.ServiceAdapter{}).ServeHTTPWithPortName)
 	mu.HandleFunc(BasePath+ServicePortStagCtagTpIDPath, (&onosnbi.ServiceAdapter{}).ServeHTTPWithPortName)
@@ -97,6 +100,7 @@
 	mu.HandleFunc(BasePath+OltFlowServicePath, (&onosnbi.OltFlowServiceHandle{}).ServeHTTP)
 	mu.HandleFunc(BasePath+NetConfigPath, (&NetConfigHandle{}).NetConfigServeHTTP)
 	mu.HandleFunc(BasePath+DeviceConfigPath, (&onosnbi.DeviceConfigHandle{}).ServeHTTP)
+	mu.HandleFunc(BasePath+FlowProvisionStatus, (&SubscriberHandle{}).StatusServeHTTP)
 
 	err := http.ListenAndServe(":8181", mu)
 	logger.Infow(ctx, "Rest Server Started", log.Fields{"Error": err})
diff --git a/voltha-go-controller/nbi/subscriber.go b/voltha-go-controller/nbi/subscriber.go
index 7fa3060..c9ceaee 100644
--- a/voltha-go-controller/nbi/subscriber.go
+++ b/voltha-go-controller/nbi/subscriber.go
@@ -98,6 +98,16 @@
 	}
 }
 
+func (sh *SubscriberHandle) StatusServeHTTP(w http.ResponseWriter, r *http.Request) {
+	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
+	switch r.Method {
+	case cGet:
+		sh.GetSubscriberAndFlowProvisionStatus(context.Background(), w, r)
+	default:
+		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
+	}
+}
+
 // AddSubscriberInfo to add service
 func (sh *SubscriberHandle) AddSubscriberInfo(cntx context.Context, w http.ResponseWriter, r *http.Request) {
 	// Get the payload to process the request
@@ -282,3 +292,23 @@
 	// HTTP response with 202 accepted for service delete request
 	w.WriteHeader(http.StatusAccepted)
 }
+
+// DelSubscriberInfo to delete service
+func (sh *SubscriberHandle) GetSubscriberAndFlowProvisionStatus(cntx context.Context, w http.ResponseWriter, r *http.Request) {
+	vars := mux.Vars(r)
+	portName := vars["portName"]
+	logger.Debugw(ctx, "Received-northbound-GetSubscriberProvisionStatus-request", log.Fields{"req": portName})
+	flowProvisionStatus := app.GetApplication().GetFlowProvisionStatus(cntx, portName)
+	flowProvisionStatusRes, err := json.Marshal(flowProvisionStatus)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling flowProvisionStatus response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(flowProvisionStatusRes)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending flowProvisionStatus response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+}