VOL-3121 - Removing usage of device.Ports

Changed device.Ports usages to GetDevicePort() and ListDevicePorts()
Added port type filter to PortsStateUpdate()

Change-Id: I4fab819a909379ee71e70eb48ac44044e9810185
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index fe30de5..2463482 100644
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -29,12 +29,11 @@
 	"sync"
 	"time"
 
-	"github.com/opencord/voltha-lib-go/v3/pkg/flows"
-
 	"github.com/cenkalti/backoff/v3"
 	"github.com/gogo/protobuf/proto"
 	"github.com/golang/protobuf/ptypes"
 	"github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
+	"github.com/opencord/voltha-lib-go/v3/pkg/flows"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
 	"github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
 	"github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
@@ -269,28 +268,19 @@
 		return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
 	}
 
-	device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
-	if err != nil || device == nil {
-		return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
-	}
-	if device.Ports != nil {
-		for _, dPort := range device.Ports {
-			if dPort.Type == portType && dPort.PortNo == portNum {
-				logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
-				if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
-					return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
-						"device-id":   dh.device.Id,
-						"port-type":   portType,
-						"port-number": portNum,
-						"oper-status": operStatus}, err)
-
-				}
-				return nil
-			}
+	if port, err := dh.coreProxy.GetDevicePort(context.TODO(), dh.device.Id, portNum); err == nil && port.Type == portType {
+		log.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
+		if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
+			return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
+				"device-id":   dh.device.Id,
+				"port-type":   portType,
+				"port-number": portNum,
+				"oper-status": operStatus}, err).Log()
 		}
+		return nil
 	}
+	// Now create Port
 	capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
-	//    Now create  Port
 	port := &voltha.Port{
 		PortNo:     portNum,
 		Label:      label,
@@ -711,14 +701,14 @@
 		return nil
 	}
 
-	device, err = dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
-	if err != nil || device == nil {
+	ports, err := dh.coreProxy.ListDevicePorts(context.TODO(), dh.device.Id)
+	if err != nil {
 		/*TODO: needs to handle error scenarios */
-		return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
+		return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
 	}
-	dh.populateActivePorts(ctx, device)
-	if err := dh.disableAdminDownPorts(ctx, device); err != nil {
-		return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
+	dh.populateActivePorts(ctx, ports)
+	if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
+		return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
 	}
 
 	if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
@@ -817,8 +807,11 @@
 			return
 		case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
 
-			ports := make([]*voltha.Port, len(dh.device.Ports))
-			copy(ports, dh.device.Ports)
+			ports, err := dh.coreProxy.ListDevicePorts(context.Background(), dh.device.Id)
+			if err != nil {
+				logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
+				continue
+			}
 			for _, port := range ports {
 				// NNI Stats
 				if port.Type == voltha.Port_ETHERNET_NNI {
@@ -1489,15 +1482,9 @@
 	//Update device Admin state
 	dh.device = cloned
 	// Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
-	for _, port := range cloned.Ports {
-		if port.GetType() == voltha.Port_PON_OLT {
-			if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
-				voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
-				return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
-			}
-		}
+	if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, ^uint32(1<<voltha.Port_PON_OLT), voltha.OperStatus_UNKNOWN); err != nil {
+		return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
 	}
-
 	logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
 	return nil
 }
@@ -1532,7 +1519,6 @@
 //Device Port-State: ACTIVE
 //Device Oper-State: ACTIVE
 func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
-
 	if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
 		if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
 			return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
@@ -1540,21 +1526,24 @@
 	}
 	logger.Debug(ctx, "olt-reenabled")
 
-	cloned := proto.Clone(device).(*voltha.Device)
 	// Update the all ports state on that device to enable
 
-	if err := dh.disableAdminDownPorts(ctx, device); err != nil {
+	ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
+	if err != nil {
+		return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device": device.Id}, err)
+	}
+	if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
 		return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
 	}
 	//Update the device oper status as ACTIVE
-	cloned.OperStatus = voltha.OperStatus_ACTIVE
-	dh.device = cloned
+	device.OperStatus = voltha.OperStatus_ACTIVE
+	dh.device = device
 
-	if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
+	if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), device.Id, device.ConnectStatus, device.OperStatus); err != nil {
 		return olterrors.NewErrAdapter("state-update-failed", log.Fields{
 			"device-id":      device.Id,
-			"connect-status": cloned.ConnectStatus,
-			"oper-status":    cloned.OperStatus}, err)
+			"connect-status": device.ConnectStatus,
+			"oper-status":    device.OperStatus}, err)
 	}
 
 	logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
@@ -1928,7 +1917,7 @@
 		if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
 			olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
 		}
-		if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
+		if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
 			olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
 		}
 		go dh.cleanupDeviceResources(ctx)
@@ -2008,11 +1997,10 @@
 }
 
 //disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
-func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, device *voltha.Device) error {
-	cloned := proto.Clone(device).(*voltha.Device)
+func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
 	// Disable the port and update the oper_port_status to core
 	// if the Admin state of the port is disabled on reboot and re-enable device.
-	for _, port := range cloned.Ports {
+	for _, port := range ports {
 		if port.AdminState == common.AdminState_DISABLED {
 			if err := dh.DisablePort(ctx, port); err != nil {
 				return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
@@ -2025,9 +2013,9 @@
 }
 
 //populateActivePorts to populate activePorts map
-func (dh *DeviceHandler) populateActivePorts(ctx context.Context, device *voltha.Device) {
-	logger.Infow(ctx, "populateActiveports", log.Fields{"Device": device})
-	for _, port := range device.Ports {
+func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
+	logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
+	for _, port := range ports {
 		if port.Type == voltha.Port_ETHERNET_NNI {
 			if port.OperStatus == voltha.OperStatus_ACTIVE {
 				dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
diff --git a/internal/pkg/core/device_handler_test.go b/internal/pkg/core/device_handler_test.go
index 38affa0..1507f2f 100644
--- a/internal/pkg/core/device_handler_test.go
+++ b/internal/pkg/core/device_handler_test.go
@@ -44,20 +44,16 @@
 )
 
 func newMockCoreProxy() *mocks.MockCoreProxy {
-	mcp := mocks.MockCoreProxy{}
-	mcp.Devices = make(map[string]*voltha.Device)
+	mcp := mocks.MockCoreProxy{
+		Devices:     make(map[string]*voltha.Device),
+		DevicePorts: make(map[string][]*voltha.Port),
+	}
 	var pm []*voltha.PmConfig
 	mcp.Devices["olt"] = &voltha.Device{
-
 		Id:           "olt",
 		Root:         true,
 		ParentId:     "logical_device",
 		ParentPortNo: 1,
-
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "nni"},
-		},
 		ProxyAddress: &voltha.Device_ProxyAddress{
 			DeviceId:       "olt",
 			DeviceType:     "onu",
@@ -73,17 +69,17 @@
 			Metrics:      pm,
 		},
 	}
-	mcp.Devices["onu1"] = &voltha.Device{
+	mcp.DevicePorts["olt"] = []*voltha.Port{
+		{PortNo: 1, Label: "pon"},
+		{PortNo: 2, Label: "nni"},
+	}
 
+	mcp.Devices["onu1"] = &voltha.Device{
 		Id:           "1",
 		Root:         false,
 		ParentId:     "olt",
 		ParentPortNo: 1,
 
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "uni"},
-		},
 		OperStatus: 4,
 		ProxyAddress: &voltha.Device_ProxyAddress{
 			OnuId:          1,
@@ -99,15 +95,16 @@
 			Metrics:      pm,
 		},
 	}
+	mcp.DevicePorts["onu1"] = []*voltha.Port{
+		{PortNo: 1, Label: "pon"},
+		{PortNo: 2, Label: "uni"},
+	}
+
 	mcp.Devices["onu2"] = &voltha.Device{
 		Id:         "2",
 		Root:       false,
 		ParentId:   "olt",
 		OperStatus: 2,
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "uni"},
-		},
 
 		ParentPortNo: 1,
 
@@ -125,6 +122,10 @@
 			Metrics:      pm,
 		},
 	}
+	mcp.DevicePorts["onu2"] = []*voltha.Port{
+		{PortNo: 1, Label: "pon"},
+		{PortNo: 2, Label: "uni"},
+	}
 	return &mcp
 }
 func newMockDeviceHandler() *DeviceHandler {
@@ -132,10 +133,6 @@
 		Id:       "olt",
 		Root:     true,
 		ParentId: "logical_device",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon", Type: voltha.Port_PON_OLT},
-			{PortNo: 2, Label: "nni", Type: voltha.Port_ETHERNET_NNI},
-		},
 		ProxyAddress: &voltha.Device_ProxyAddress{
 			DeviceId:       "olt",
 			DeviceType:     "onu",
@@ -1130,12 +1127,11 @@
 		dh *DeviceHandler
 	}
 	dh := newMockDeviceHandler()
-	ports := []*voltha.Port{
+	dh.coreProxy.(*mocks.MockCoreProxy).DevicePorts[dh.device.Id] = []*voltha.Port{
 		{PortNo: 1, Label: "pon", Type: voltha.Port_PON_OLT},
 		{PortNo: 1048577, Label: "nni", Type: voltha.Port_ETHERNET_NNI},
 		{PortNo: 1048578, Label: "nni", Type: voltha.Port_ETHERNET_NNI},
 	}
-	dh.device.Ports = ports
 	dh.portStats.NorthBoundPort = make(map[uint32]*NniPort)
 	dh.portStats.NorthBoundPort[1] = &NniPort{Name: "OLT-1"}
 	dh.portStats.NorthBoundPort[2] = &NniPort{Name: "OLT-1"}
@@ -1145,7 +1141,7 @@
 		dh.portStats.SouthBoundPort[uint32(i)] = &PonPort{DeviceID: "OLT-1"}
 	}
 	dh1 := newMockDeviceHandler()
-	dh1.device.Ports = []*voltha.Port{}
+	dh1.coreProxy.(*mocks.MockCoreProxy).DevicePorts[dh.device.Id] = []*voltha.Port{}
 	tests := []struct {
 		name string
 		args args
diff --git a/internal/pkg/core/openolt_eventmgr.go b/internal/pkg/core/openolt_eventmgr.go
index fc9a342..6f1fd68 100644
--- a/internal/pkg/core/openolt_eventmgr.go
+++ b/internal/pkg/core/openolt_eventmgr.go
@@ -617,26 +617,17 @@
 
 // oltIntfOperIndication handles Up and Down state of an OLT PON ports
 func (em *OpenOltEventMgr) oltIntfOperIndication(ctx context.Context, ifindication *oop.IntfOperIndication, deviceID string, raisedTs int64) error {
-	var de voltha.DeviceEvent
-	portID := IntfIDToPortNo(ifindication.IntfId, voltha.Port_PON_OLT)
-	device, err := em.handler.coreProxy.GetDevice(context.Background(), deviceID, deviceID)
-	if err != nil {
-		return olterrors.NewErrAdapter("error-while-fetching-device-object", log.Fields{"DeviceId": deviceID}, err)
-	}
-	context := make(map[string]string)
-	for _, port := range device.Ports {
-		if port.PortNo == portID {
-			// Events are suppressed if the Port Adminstate is not enabled.
-			if port.AdminState != common.AdminState_ENABLED {
-				logger.Debugw(ctx, "port-disable/enable-event-not-generated--the-port-is-not-enabled-by-operator", log.Fields{"deviceId": deviceID, "port": port})
-				return nil
-			}
-			break
-		}
+	portNo := IntfIDToPortNo(ifindication.IntfId, voltha.Port_PON_OLT)
+	if port, err := em.handler.coreProxy.GetDevicePort(ctx, deviceID, portNo); err != nil {
+		logger.Warnw(ctx, "Error while fetching port object", log.Fields{"device-id": deviceID, "error": err})
+	} else if port.AdminState != common.AdminState_ENABLED {
+		logger.Debugw(ctx, "port-disable/enable-event-not-generated--the-port-is-not-enabled-by-operator", log.Fields{"device-id": deviceID, "port": port})
+		return nil
 	}
 	/* Populating event context */
-	context[ContextOltPonIntfOperState] = ifindication.GetOperState()
+	context := map[string]string{ContextOltPonIntfOperState: ifindication.GetOperState()}
 	/* Populating device event body */
+	var de voltha.DeviceEvent
 	de.Context = context
 	de.ResourceId = deviceID
 
diff --git a/internal/pkg/core/openolt_test.go b/internal/pkg/core/openolt_test.go
index 764cb20..a2ac77b 100644
--- a/internal/pkg/core/openolt_test.go
+++ b/internal/pkg/core/openolt_test.go
@@ -25,6 +25,10 @@
 import (
 	"context"
 	"errors"
+	"reflect"
+	"sync"
+	"testing"
+
 	com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
 	fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
 	"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
@@ -35,9 +39,6 @@
 	"github.com/opencord/voltha-protos/v3/go/openflow_13"
 	ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"reflect"
-	"sync"
-	"testing"
 )
 
 // mocks the OpenOLT struct.
@@ -81,14 +82,10 @@
 
 // mockDevice mocks Device.
 func mockDevice() *voltha.Device {
-	device := &voltha.Device{
+	return &voltha.Device{
 		Id:       "olt",
 		Root:     true,
 		ParentId: "logical_device",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "nni"},
-		},
 		ProxyAddress: &voltha.Device_ProxyAddress{
 			DeviceId:       "olt",
 			DeviceType:     "onu",
@@ -97,7 +94,6 @@
 		},
 		ConnectStatus: 1,
 	}
-	return device
 }
 
 func TestNewOpenOLT(t *testing.T) {
diff --git a/internal/pkg/core/statsmanager_test.go b/internal/pkg/core/statsmanager_test.go
index 67b9a6a..cfbc04a 100644
--- a/internal/pkg/core/statsmanager_test.go
+++ b/internal/pkg/core/statsmanager_test.go
@@ -31,10 +31,6 @@
 		Id:       "olt",
 		Root:     true,
 		ParentId: "logical_device",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon", Type: voltha.Port_ETHERNET_UNI},
-			{PortNo: 2, Label: "nni", Type: voltha.Port_ETHERNET_NNI},
-		},
 		ProxyAddress: &voltha.Device_ProxyAddress{
 			DeviceId:       "olt",
 			DeviceType:     "onu",