VOL-2867 - Removed unnescessary proto.Clone() in getDevice() and getLogicalDevice().

Also renamed getDevice() to getDeviceReadOnly(), getLogicalDevice() to getLogicalDeviceReadOnly(), and getDeviceReadOnly() to getDeviceReadOnlyWithoutLock().
Callers of *ReadOnly() functions must not modify the returned structures.
Also fixed places where lock was not acquired before calling getDevice().
Related to VOL-3356.

Change-Id: I9913a76a497c4d977457edaea3b199a24a3a5cb8
diff --git a/rw_core/core/device/agent.go b/rw_core/core/device/agent.go
index 6053d65..516cc91 100755
--- a/rw_core/core/device/agent.go
+++ b/rw_core/core/device/agent.go
@@ -99,7 +99,7 @@
 func (agent *Agent) start(ctx context.Context, deviceToCreate *voltha.Device) (*voltha.Device, error) {
 	needToStart := false
 	if agent.startOnce.Do(func() { needToStart = true }); !needToStart {
-		return agent.getDevice(ctx)
+		return agent.getDeviceReadOnly(ctx)
 	}
 	var startSucceeded bool
 	defer func() {
@@ -152,7 +152,7 @@
 	startSucceeded = true
 	logger.Debugw(ctx, "device-agent-started", log.Fields{"device-id": agent.deviceID})
 
-	return agent.getDevice(ctx)
+	return agent.getDeviceReadOnly(ctx)
 }
 
 // stop stops the device agent.  Not much to do for now
@@ -242,18 +242,18 @@
 	}
 }
 
-// getDevice returns the device data from cache
-func (agent *Agent) getDevice(ctx context.Context) (*voltha.Device, error) {
+// getDeviceReadOnly returns a device which MUST NOT be modified, but is safe to keep forever.
+func (agent *Agent) getDeviceReadOnly(ctx context.Context) (*voltha.Device, error) {
 	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
 		return nil, err
 	}
 	defer agent.requestQueue.RequestComplete()
-	return proto.Clone(agent.device).(*voltha.Device), nil
+	return agent.device, nil
 }
 
-// getDeviceReadOnly returns a device which MUST NOT be modified, but is safe to keep forever.  This is very efficient.
+// getDeviceReadOnlyWithoutLock returns a device which MUST NOT be modified, but is safe to keep forever.  This is very efficient.
 // The device lock MUST be held by the caller.
-func (agent *Agent) getDeviceReadOnly() *voltha.Device {
+func (agent *Agent) getDeviceReadOnlyWithoutLock() *voltha.Device {
 	return agent.device
 }
 
@@ -270,7 +270,7 @@
 	}
 	logger.Debugw(ctx, "enableDevice", log.Fields{"device-id": agent.deviceID})
 
-	oldDevice := agent.getDeviceReadOnly()
+	oldDevice := agent.getDeviceReadOnlyWithoutLock()
 	if oldDevice.AdminState == voltha.AdminState_ENABLED {
 		logger.Warnw(ctx, "device-already-enabled", log.Fields{"device-id": agent.deviceID})
 		agent.requestQueue.RequestComplete()
@@ -434,7 +434,7 @@
 	defer agent.requestQueue.RequestComplete()
 	logger.Debugw(ctx, "rebootDevice", log.Fields{"device-id": agent.deviceID})
 
-	device := agent.getDeviceReadOnly()
+	device := agent.getDeviceReadOnlyWithoutLock()
 	subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
 	ch, err := agent.adapterProxy.RebootDevice(subCtx, device)
 	if err != nil {
@@ -490,11 +490,11 @@
 func (agent *Agent) getSwitchCapability(ctx context.Context) (*ic.SwitchCapability, error) {
 	logger.Debugw(ctx, "getSwitchCapability", log.Fields{"device-id": agent.deviceID})
 
-	cloned, err := agent.getDevice(ctx)
+	device, err := agent.getDeviceReadOnly(ctx)
 	if err != nil {
 		return nil, err
 	}
-	ch, err := agent.adapterProxy.GetOfpDeviceInfo(ctx, cloned)
+	ch, err := agent.adapterProxy.GetOfpDeviceInfo(ctx, device)
 	if err != nil {
 		return nil, err
 	}
@@ -634,7 +634,7 @@
 	defer agent.requestQueue.RequestComplete()
 	logger.Debugw(ctx, "simulateAlarm", log.Fields{"id": agent.deviceID})
 
-	device := agent.getDeviceReadOnly()
+	device := agent.getDeviceReadOnlyWithoutLock()
 
 	subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
 	ch, err := agent.adapterProxy.SimulateAlarm(subCtx, device, simulateReq)
diff --git a/rw_core/core/device/agent_flow.go b/rw_core/core/device/agent_flow.go
index 09ca7ed..94376d1 100644
--- a/rw_core/core/device/agent_flow.go
+++ b/rw_core/core/device/agent_flow.go
@@ -49,7 +49,10 @@
 		logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": newFlows})
 		return coreutils.DoneResponse(), nil
 	}
-	device := agent.getDeviceReadOnly()
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+	}
 	dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
 	if err != nil {
 		return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
@@ -127,7 +130,10 @@
 		return coreutils.DoneResponse(), nil
 	}
 
-	device := agent.getDeviceReadOnly()
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+	}
 	dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
 	if err != nil {
 		return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
@@ -183,7 +189,10 @@
 		return coreutils.DoneResponse(), nil
 	}
 
-	device := agent.getDeviceReadOnly()
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+	}
 	if device.OperStatus != voltha.OperStatus_ACTIVE || device.ConnectStatus != voltha.ConnectStatus_REACHABLE || device.AdminState != voltha.AdminState_ENABLED {
 		return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "invalid device states")
 	}
diff --git a/rw_core/core/device/agent_group.go b/rw_core/core/device/agent_group.go
index da2b7c5..96254e4 100644
--- a/rw_core/core/device/agent_group.go
+++ b/rw_core/core/device/agent_group.go
@@ -50,7 +50,10 @@
 		return coreutils.DoneResponse(), nil
 	}
 
-	device := agent.getDeviceReadOnly()
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+	}
 	dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
 	if err != nil {
 		return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
@@ -128,7 +131,10 @@
 		logger.Debugw(ctx, "nothing-to-delete", log.Fields{"device-id": agent.deviceID})
 		return coreutils.DoneResponse(), nil
 	}
-	device := agent.getDeviceReadOnly()
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+	}
 	dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
 	if err != nil {
 		return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
@@ -184,7 +190,10 @@
 		return coreutils.DoneResponse(), nil
 	}
 
-	device := agent.getDeviceReadOnly()
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+	}
 	if device.OperStatus != voltha.OperStatus_ACTIVE || device.ConnectStatus != voltha.ConnectStatus_REACHABLE || device.AdminState != voltha.AdminState_ENABLED {
 		return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "invalid device states-oper-%s-connect-%s-admin-%s", device.OperStatus, device.ConnectStatus, device.AdminState)
 	}
diff --git a/rw_core/core/device/agent_image.go b/rw_core/core/device/agent_image.go
index 3bc91ca..0dc56bf 100644
--- a/rw_core/core/device/agent_image.go
+++ b/rw_core/core/device/agent_image.go
@@ -84,7 +84,7 @@
 	logger.Debugw(ctx, "cancelImageDownload", log.Fields{"device-id": agent.deviceID})
 
 	// Verify whether the Image is in the list of image being downloaded
-	device := agent.getDeviceReadOnly()
+	device := agent.getDeviceReadOnlyWithoutLock()
 	if !isImageRegistered(img, device) {
 		agent.requestQueue.RequestComplete()
 		return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, image-not-registered:%s", agent.deviceID, img.Name)
@@ -124,7 +124,7 @@
 	logger.Debugw(ctx, "activateImage", log.Fields{"device-id": agent.deviceID})
 
 	// Verify whether the Image is in the list of image being downloaded
-	device := agent.getDeviceReadOnly()
+	device := agent.getDeviceReadOnlyWithoutLock()
 	if !isImageRegistered(img, device) {
 		agent.requestQueue.RequestComplete()
 		return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, image-not-registered:%s", agent.deviceID, img.Name)
@@ -167,7 +167,7 @@
 	logger.Debugw(ctx, "revertImage", log.Fields{"device-id": agent.deviceID})
 
 	// Verify whether the Image is in the list of image being downloaded
-	device := agent.getDeviceReadOnly()
+	device := agent.getDeviceReadOnlyWithoutLock()
 	if !isImageRegistered(img, device) {
 		agent.requestQueue.RequestComplete()
 		return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, image-not-registered:%s", agent.deviceID, img.Name)
@@ -205,7 +205,7 @@
 	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
 		return nil, err
 	}
-	device := agent.getDeviceReadOnly()
+	device := agent.getDeviceReadOnlyWithoutLock()
 	ch, err := agent.adapterProxy.GetImageDownloadStatus(ctx, device, img)
 	agent.requestQueue.RequestComplete()
 	if err != nil {
@@ -255,13 +255,12 @@
 }
 
 func (agent *Agent) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return nil, err
-	}
-	defer agent.requestQueue.RequestComplete()
 	logger.Debugw(ctx, "getImageDownload", log.Fields{"device-id": agent.deviceID})
 
-	device := agent.getDeviceReadOnly()
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return nil, status.Errorf(codes.Aborted, "%s", err)
+	}
 	for _, image := range device.ImageDownloads {
 		if image.Id == img.Id && image.Name == img.Name {
 			return image, nil
@@ -271,11 +270,11 @@
 }
 
 func (agent *Agent) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return nil, err
-	}
-	defer agent.requestQueue.RequestComplete()
 	logger.Debugw(ctx, "listImageDownloads", log.Fields{"device-id": agent.deviceID})
 
-	return &voltha.ImageDownloads{Items: agent.getDeviceReadOnly().ImageDownloads}, nil
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return nil, status.Errorf(codes.Aborted, "%s", err)
+	}
+	return &voltha.ImageDownloads{Items: device.ImageDownloads}, nil
 }
diff --git a/rw_core/core/device/agent_pm_config.go b/rw_core/core/device/agent_pm_config.go
index 033e6f4..8677029 100644
--- a/rw_core/core/device/agent_pm_config.go
+++ b/rw_core/core/device/agent_pm_config.go
@@ -22,6 +22,8 @@
 	"github.com/gogo/protobuf/proto"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
 )
 
 func (agent *Agent) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
@@ -59,11 +61,11 @@
 }
 
 func (agent *Agent) listPmConfigs(ctx context.Context) (*voltha.PmConfigs, error) {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return nil, err
-	}
-	defer agent.requestQueue.RequestComplete()
 	logger.Debugw(ctx, "listPmConfigs", log.Fields{"device-id": agent.deviceID})
 
-	return agent.getDeviceReadOnly().PmConfigs, nil
+	device, err := agent.getDeviceReadOnly(ctx)
+	if err != nil {
+		return nil, status.Errorf(codes.Aborted, "%s", err)
+	}
+	return device.PmConfigs, nil
 }
diff --git a/rw_core/core/device/agent_port.go b/rw_core/core/device/agent_port.go
index 5ac7aca..2840235 100644
--- a/rw_core/core/device/agent_port.go
+++ b/rw_core/core/device/agent_port.go
@@ -118,7 +118,7 @@
 func (agent *Agent) deleteAllPorts(ctx context.Context) error {
 	logger.Debugw(ctx, "deleteAllPorts", log.Fields{"deviceId": agent.deviceID})
 
-	device, err := agent.getDevice(ctx)
+	device, err := agent.getDeviceReadOnly(ctx)
 	if err != nil {
 		return err
 	}
@@ -238,7 +238,7 @@
 	}
 
 	//send request to adapter
-	device, err := agent.getDevice(ctx)
+	device, err := agent.getDeviceReadOnly(ctx)
 	if err != nil {
 		return err
 	}
@@ -274,7 +274,7 @@
 	}
 
 	//send request to adapter
-	device, err := agent.getDevice(ctx)
+	device, err := agent.getDeviceReadOnly(ctx)
 	if err != nil {
 		return err
 	}
diff --git a/rw_core/core/device/agent_test.go b/rw_core/core/device/agent_test.go
index 9249198..c8928e2 100755
--- a/rw_core/core/device/agent_test.go
+++ b/rw_core/core/device/agent_test.go
@@ -179,7 +179,7 @@
 }
 
 func (dat *DATest) updateDeviceConcurrently(t *testing.T, da *Agent, globalWG *sync.WaitGroup) {
-	originalDevice, err := da.getDevice(context.Background())
+	originalDevice, err := da.getDeviceReadOnly(context.Background())
 	originalDevicePorts := da.listDevicePorts()
 	assert.Nil(t, err)
 	assert.NotNil(t, originalDevice)
@@ -242,7 +242,7 @@
 	expectedChange.Vlan = vlan
 	expectedChange.Reason = reason
 
-	updatedDevice, _ := da.getDevice(context.Background())
+	updatedDevice, _ := da.getDeviceReadOnly(context.Background())
 	updatedDevicePorts := da.listDevicePorts()
 	assert.NotNil(t, updatedDevice)
 	fmt.Printf("1 %+v\n", expectedChange)
diff --git a/rw_core/core/device/logical_agent.go b/rw_core/core/device/logical_agent.go
index 07f85e8..a581c5b 100644
--- a/rw_core/core/device/logical_agent.go
+++ b/rw_core/core/device/logical_agent.go
@@ -208,13 +208,13 @@
 	return returnErr
 }
 
-// GetLogicalDevice returns the latest logical device data
-func (agent *LogicalAgent) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
+// GetLogicalDeviceReadOnly returns the latest logical device data
+func (agent *LogicalAgent) GetLogicalDeviceReadOnly(ctx context.Context) (*voltha.LogicalDevice, error) {
 	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
 		return nil, err
 	}
 	defer agent.requestQueue.RequestComplete()
-	return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice), nil
+	return agent.logicalDevice, nil
 }
 
 func (agent *LogicalAgent) addFlowsAndGroupsToDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
diff --git a/rw_core/core/device/logical_manager.go b/rw_core/core/device/logical_manager.go
index cf2beed..ec4a528 100644
--- a/rw_core/core/device/logical_manager.go
+++ b/rw_core/core/device/logical_manager.go
@@ -90,7 +90,7 @@
 func (ldMgr *LogicalManager) GetLogicalDevice(ctx context.Context, id *voltha.ID) (*voltha.LogicalDevice, error) {
 	logger.Debugw(ctx, "getlogicalDevice", log.Fields{"logicaldeviceid": id})
 	if agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id); agent != nil {
-		return agent.GetLogicalDevice(ctx)
+		return agent.GetLogicalDeviceReadOnly(ctx)
 	}
 	return nil, status.Errorf(codes.NotFound, "%s", id)
 }
@@ -273,7 +273,7 @@
 	// Get the device
 	var device *voltha.Device
 	var err error
-	if device, err = ldMgr.deviceMgr.getDevice(ctx, deviceID); err != nil {
+	if device, err = ldMgr.deviceMgr.getDeviceReadOnly(ctx, deviceID); err != nil {
 		return nil, err
 	}
 	return ldMgr.getLogicalDeviceID(ctx, device)
diff --git a/rw_core/core/device/manager.go b/rw_core/core/device/manager.go
index ad20aac..19dab3d 100755
--- a/rw_core/core/device/manager.go
+++ b/rw_core/core/device/manager.go
@@ -297,15 +297,17 @@
 	return nil
 }
 
+// GetDevice exists primarily to implement the gRPC interface.
+// Internal functions should call getDeviceReadOnly instead.
 func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
-	return dMgr.getDevice(ctx, id.Id)
+	return dMgr.getDeviceReadOnly(ctx, id.Id)
 }
 
-// getDevice will returns a device, either from memory or from the dB, if present
-func (dMgr *Manager) getDevice(ctx context.Context, id string) (*voltha.Device, error) {
-	logger.Debugw(ctx, "getDevice", log.Fields{"deviceid": id})
+// getDeviceReadOnly will returns a device, either from memory or from the dB, if present
+func (dMgr *Manager) getDeviceReadOnly(ctx context.Context, id string) (*voltha.Device, error) {
+	logger.Debugw(ctx, "getDeviceReadOnly", log.Fields{"deviceid": id})
 	if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
-		return agent.getDevice(ctx)
+		return agent.getDeviceReadOnly(ctx)
 	}
 	return nil, status.Errorf(codes.NotFound, "%s", id)
 }
@@ -337,7 +339,7 @@
 	var foundChildDevice *voltha.Device
 	for childDeviceID := range childDeviceIds {
 		var found bool
-		if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
+		if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
 
 			foundOnuID := false
 			if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
@@ -394,7 +396,7 @@
 
 	var foundChildDevice *voltha.Device
 	for childDeviceID := range childDeviceIds {
-		if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
+		if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
 			if searchDevice.ProxyAddress == proxyAddress {
 				foundChildDevice = searchDevice
 				break
@@ -578,7 +580,7 @@
 		return err
 	}
 	// Get the loaded device details
-	device, err := dAgent.getDevice(ctx)
+	device, err := dAgent.getDeviceReadOnly(ctx)
 	if err != nil {
 		return err
 	}
@@ -772,7 +774,7 @@
 	// Notify the logical device manager to setup a logical port, if needed.  If the added port is an NNI or UNI
 	// then a logical port will be added to the logical device and the device route generated.  If the port is a
 	// PON port then only the device graph will be generated.
-	device, err := dMgr.getDevice(ctx, deviceID)
+	device, err := dMgr.getDeviceReadOnly(ctx, deviceID)
 	if err != nil {
 		return err
 	}
@@ -950,10 +952,9 @@
 		// Notify the logical device manager to remove all logical ports, if needed.
 		// At this stage the device itself may gave been deleted already at a DeleteAllPorts
 		// typically is part of a device deletion phase.
-		if device, err := dMgr.getDevice(ctx, deviceID); err == nil {
+		if device, err := dMgr.getDeviceReadOnly(ctx, deviceID); err == nil {
 			go func() {
-				err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(context.Background(), device)
-				if err != nil {
+				if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(context.Background(), device); err != nil {
 					logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
 				}
 			}()
@@ -1097,7 +1098,7 @@
 	// Get the logical device Id based on the deviceId
 	var device *voltha.Device
 	var err error
-	if device, err = dMgr.getDevice(ctx, deviceID); err != nil {
+	if device, err = dMgr.getDeviceReadOnly(ctx, deviceID); err != nil {
 		logger.Errorw(ctx, "device-not-found", log.Fields{"deviceId": deviceID})
 		return err
 	}
@@ -1166,7 +1167,7 @@
 		// childDevice is the parent device
 		return childDevice
 	}
-	parentDevice, _ := dMgr.getDevice(ctx, childDevice.ParentId)
+	parentDevice, _ := dMgr.getDeviceReadOnly(ctx, childDevice.ParentId)
 	return parentDevice
 }
 
@@ -1174,7 +1175,7 @@
 //cannot manage the child devices.  This will trigger the Core to disable all the child devices.
 func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
 	logger.Debug(ctx, "ChildDevicesLost")
-	parentDevice, err := dMgr.getDevice(ctx, parentDeviceID)
+	parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentDeviceID)
 	if err != nil {
 		logger.Warnw(ctx, "failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
 		return err
@@ -1295,7 +1296,7 @@
 	if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
 		childDevices := make([]*voltha.Device, 0)
 		for deviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
-			if d, e := dMgr.getDevice(ctx, deviceID); e == nil && d != nil {
+			if d, e := dMgr.getDeviceReadOnly(ctx, deviceID); e == nil && d != nil {
 				childDevices = append(childDevices, d)
 			}
 		}
@@ -1438,11 +1439,11 @@
 // GetImages returns all images for a specific device entry
 func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
 	logger.Debugw(ctx, "GetImages", log.Fields{"device-id": id.Id})
-	device, err := dMgr.getDevice(ctx, id.Id)
+	device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
 	if err != nil {
 		return nil, err
 	}
-	return device.GetImages(), nil
+	return device.Images, nil
 }
 
 func (dMgr *Manager) NotifyInvalidTransition(ctx context.Context, device *voltha.Device) error {
@@ -1471,7 +1472,7 @@
 
 // GetParentDeviceID returns parent device id, either from memory or from the dB, if present
 func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
-	if device, _ := dMgr.getDevice(ctx, deviceID); device != nil {
+	if device, _ := dMgr.getDeviceReadOnly(ctx, deviceID); device != nil {
 		logger.Infow(ctx, "GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
 		return device.ParentId
 	}
@@ -1542,11 +1543,11 @@
 
 func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
 	log.Debugw("getExtValue", log.Fields{"onu-id": value.Id})
-	cDevice, err := dMgr.getDevice(ctx, value.Id)
+	cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
 	if err != nil {
 		return nil, status.Errorf(codes.Aborted, "%s", err.Error())
 	}
-	pDevice, err := dMgr.getDevice(ctx, cDevice.ParentId)
+	pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
 	if err != nil {
 		return nil, status.Errorf(codes.Aborted, "%s", err.Error())
 	}
diff --git a/rw_core/coreif/logical_device_agent_if.go b/rw_core/coreif/logical_device_agent_if.go
index 43422c1..f3c8644 100644
--- a/rw_core/coreif/logical_device_agent_if.go
+++ b/rw_core/coreif/logical_device_agent_if.go
@@ -22,14 +22,13 @@
 
 import (
 	"context"
+
 	"github.com/opencord/voltha-go/rw_core/route"
-	"github.com/opencord/voltha-protos/v3/go/voltha"
 )
 
 // LogicalDeviceAgent represents a generic agent
 type LogicalDeviceAgent interface {
 	GetDeviceRoutes() *route.DeviceRoutes
-	GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error)
 	GetWildcardInputPorts(ctx context.Context, excludePort uint32) map[uint32]struct{}
 	GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error)
 	GetNNIPorts() map[uint32]struct{}