[VOL-4291] Rw-core updates for gRPC migration
Change-Id: I8d5a554409115b29318089671ca4e1ab3fa98810
diff --git a/rw_core/core/device/agent.go b/rw_core/core/device/agent.go
index cd879c6..1a83cb2 100755
--- a/rw_core/core/device/agent.go
+++ b/rw_core/core/device/agent.go
@@ -25,9 +25,11 @@
"sync"
"time"
+ "github.com/opencord/voltha-protos/v5/go/adapter_services"
+ "github.com/opencord/voltha-protos/v5/go/core"
+
"github.com/cenkalti/backoff/v3"
"github.com/gogo/protobuf/proto"
- "github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/empty"
"github.com/opencord/voltha-go/rw_core/config"
"google.golang.org/grpc/codes"
@@ -38,32 +40,34 @@
"github.com/opencord/voltha-go/rw_core/core/device/flow"
"github.com/opencord/voltha-go/rw_core/core/device/group"
"github.com/opencord/voltha-go/rw_core/core/device/port"
- "github.com/opencord/voltha-go/rw_core/core/device/remote"
"github.com/opencord/voltha-go/rw_core/core/device/transientstate"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/common"
- "github.com/opencord/voltha-protos/v4/go/extension"
- ic "github.com/opencord/voltha-protos/v4/go/inter_container"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ "github.com/opencord/voltha-protos/v5/go/extension"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
)
+var errReconcileAborted = errors.New("reconcile aborted")
+var errContextExpired = errors.New("context expired")
+
// Agent represents device agent attributes
type Agent struct {
deviceID string
parentID string
deviceType string
+ adapterEndpoint string
isRootDevice bool
- adapterProxy *remote.AdapterProxy
adapterMgr *adapter.Manager
deviceMgr *Manager
dbProxy *model.Proxy
exitChannel chan int
device *voltha.Device
requestQueue *coreutils.RequestQueue
- defaultTimeout time.Duration
+ internalTimeout time.Duration
+ rpcTimeout time.Duration
startOnce sync.Once
stopOnce sync.Once
stopped bool
@@ -78,7 +82,7 @@
}
//newAgent creates a new device agent. The device will be initialized when start() is called.
-func newAgent(ap *remote.AdapterProxy, device *voltha.Device, deviceMgr *Manager, dbPath *model.Path, deviceProxy *model.Proxy, timeout time.Duration) *Agent {
+func newAgent(device *voltha.Device, deviceMgr *Manager, dbPath *model.Path, deviceProxy *model.Proxy, internalTimeout, rpcTimeout time.Duration) *Agent {
deviceID := device.Id
if deviceID == "" {
deviceID = coreutils.CreateDeviceID()
@@ -86,15 +90,16 @@
return &Agent{
deviceID: deviceID,
- adapterProxy: ap,
isRootDevice: device.Root,
parentID: device.ParentId,
deviceType: device.Type,
+ adapterEndpoint: device.AdapterEndpoint,
deviceMgr: deviceMgr,
adapterMgr: deviceMgr.adapterMgr,
exitChannel: make(chan int, 1),
dbProxy: deviceProxy,
- defaultTimeout: timeout,
+ internalTimeout: internalTimeout,
+ rpcTimeout: rpcTimeout,
device: proto.Clone(device).(*voltha.Device),
requestQueue: coreutils.NewRequestQueue(),
config: deviceMgr.config,
@@ -132,22 +137,23 @@
} else if !have {
return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceID)
}
+ logger.Infow(ctx, "device-loaded-from-db", log.Fields{"device-id": agent.deviceID, "adapter-endpoint": device.AdapterEndpoint, "type": device.Type})
}
- agent.deviceType = device.Adapter
+ agent.deviceType = device.Type
+ agent.adapterEndpoint = device.AdapterEndpoint
agent.device = proto.Clone(device).(*voltha.Device)
// load the ports from KV to cache
agent.portLoader.Load(ctx)
agent.transientStateLoader.Load(ctx)
-
- logger.Infow(ctx, "device-loaded-from-db", log.Fields{"device-id": agent.deviceID})
} else {
// Create a new device
var desc string
+ var err error
prevState := common.AdminState_UNKNOWN
currState := common.AdminState_UNKNOWN
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
- defer agent.logDeviceUpdate(ctx, "createDevice", &prevState, &currState, operStatus, &desc)
+ defer func() { agent.logDeviceUpdate(ctx, &prevState, &currState, requestStatus, err, desc) }()
// Assumption is that AdminState, FlowGroups, and Flows are uninitialized since this
// is a new device, so populate them here before passing the device to ldProxy.Set.
@@ -162,13 +168,13 @@
device.Vlan = deviceToCreate.ProxyAddress.ChannelId
}
- // Add the initial device to the local model
- if err := agent.dbProxy.Set(ctx, agent.deviceID, device); err != nil {
- desc = fmt.Sprintf("failed-adding-device-%s: %s", agent.deviceID, err.Error())
- return nil, status.Errorf(codes.Aborted, "failed-adding-device-%s: %s", agent.deviceID, err)
+ // Save the device to the model
+ if err = agent.dbProxy.Set(ctx, agent.deviceID, device); err != nil {
+ err = status.Errorf(codes.Aborted, "failed-adding-device-%s: %s", agent.deviceID, err)
+ return nil, err
}
_ = agent.deviceMgr.Agent.SendDeviceStateChangeEvent(ctx, device.OperStatus, device.ConnectStatus, prevState, device, time.Now().Unix())
- operStatus.Code = common.OperationResp_OPERATION_SUCCESS
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
agent.device = device
}
startSucceeded = true
@@ -225,8 +231,9 @@
return // not found in kv
}
- agent.deviceType = device.Adapter
+ agent.deviceType = device.Type
agent.device = device
+ agent.adapterEndpoint = device.AdapterEndpoint
agent.portLoader.Load(ctx)
agent.transientStateLoader.Load(ctx)
@@ -234,139 +241,68 @@
}
// onSuccess is a common callback for scenarios where we receive a nil response following a request to an adapter
-// and the only action required is to publish a successful result on kafka
-func (agent *Agent) onSuccess(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
- logger.Debugw(ctx, "response-successful", log.Fields{"rpc": rpc, "device-id": agent.deviceID})
- // TODO: Post success message onto kafka
+func (agent *Agent) onSuccess(ctx context.Context, prevState, currState *common.AdminState_Types, deviceUpdateLog bool) {
+ if deviceUpdateLog {
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
+ desc := "adapter-response"
+ agent.logDeviceUpdate(ctx, prevState, currState, requestStatus, nil, desc)
+ return
+ }
+ logger.Debugw(ctx, "successful-operation", log.Fields{"device-id": agent.deviceID, "rpc": coreutils.GetRPCMetadataFromContext(ctx)})
}
// onFailure is a common callback for scenarios where we receive an error response following a request to an adapter
// and the only action required is to publish the failed result on kafka
-func (agent *Agent) onFailure(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
- if res, ok := response.(error); ok {
- logger.Errorw(ctx, "rpc-failed", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": res, "args": reqArgs})
- } else {
- logger.Errorw(ctx, "rpc-failed-invalid-error", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
- }
- // TODO: Post failure message onto kafka
-}
+func (agent *Agent) onFailure(ctx context.Context, err error, prevState, currState *common.AdminState_Types, deviceUpdateLog bool) {
+ // Send an event on kafka
+ rpce := agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, err.Error(), nil)
+ go agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
+ voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
-func (agent *Agent) waitForAdapterForceDeleteResponse(ctx context.Context, cancel context.CancelFunc, rpc string, ch chan *kafka.RpcResponse,
- onSuccess coreutils.ResponseCallback, onFailure coreutils.ResponseCallback, reqArgs ...interface{}) {
- defer cancel()
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- onFailure(ctx, rpc, status.Errorf(codes.Aborted, "channel-closed"), reqArgs)
- } else if rpcResponse.Err != nil {
- onFailure(ctx, rpc, rpcResponse.Err, reqArgs)
- } else {
- onSuccess(ctx, rpc, rpcResponse.Reply, reqArgs)
- }
- case <-ctx.Done():
- onFailure(ctx, rpc, ctx.Err(), reqArgs)
+ // Log the device update event
+ if deviceUpdateLog {
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ desc := "adapter-response"
+ agent.logDeviceUpdate(ctx, prevState, currState, requestStatus, err, desc)
+ return
}
+ logger.Errorw(ctx, "failed-operation", log.Fields{"error": err, "device-id": agent.deviceID, "rpc": coreutils.GetRPCMetadataFromContext(ctx)})
}
// onDeleteSuccess is a common callback for scenarios where we receive a nil response following a delete request
// to an adapter.
-func (agent *Agent) onDeleteSuccess(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
- logger.Debugw(ctx, "response-successful", log.Fields{"rpc": rpc, "device-id": agent.deviceID})
+func (agent *Agent) onDeleteSuccess(ctx context.Context, prevState, currState *common.AdminState_Types) {
if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- logger.Errorw(ctx, "delete-device-failure", log.Fields{"device-id": agent.deviceID, "error": err, "args": reqArgs})
+ logger.Errorw(ctx, "delete-device-failure", log.Fields{"device-id": agent.deviceID, "error": err})
}
previousDeviceTransientState := agent.getTransientState()
newDevice := agent.cloneDeviceWithoutLock()
if err := agent.updateDeviceWithTransientStateAndReleaseLock(ctx, newDevice,
- voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE, previousDeviceTransientState); err != nil {
- logger.Errorw(ctx, "delete-device-failure", log.Fields{"device-id": agent.deviceID, "error": err, "args": reqArgs})
+ core.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE, previousDeviceTransientState); err != nil {
+ logger.Errorw(ctx, "delete-device-failure", log.Fields{"device-id": agent.deviceID, "error": err})
}
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
+ desc := "adapter-response"
+ agent.logDeviceUpdate(ctx, prevState, currState, requestStatus, nil, desc)
}
// onDeleteFailure is a common callback for scenarios where we receive an error response following a delete request
// to an adapter and the only action required is to return the error response.
-func (agent *Agent) onDeleteFailure(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
- if res, ok := response.(error); ok {
- logger.Errorw(ctx, "rpc-failed", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": res, "args": reqArgs})
- } else {
- logger.Errorw(ctx, "rpc-failed-invalid-error", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
- }
+func (agent *Agent) onDeleteFailure(ctx context.Context, err error, prevState, currState *common.AdminState_Types) {
+ logger.Errorw(ctx, "rpc-failed", log.Fields{"rpc": coreutils.GetRPCMetadataFromContext(ctx), "device-id": agent.deviceID, "error": err})
+
//Only updating of transient state is required, no transition.
- if err := agent.updateTransientState(ctx, voltha.DeviceTransientState_DELETE_FAILED); err != nil {
- logger.Errorw(ctx, "failed-to-update-transient-state-as-delete-failed", log.Fields{"device-id": agent.deviceID})
+ if er := agent.updateTransientState(ctx, core.DeviceTransientState_DELETE_FAILED); er != nil {
+ logger.Errorw(ctx, "failed-to-update-transient-state-as-delete-failed", log.Fields{"device-id": agent.deviceID, "error": er})
}
+ rpce := agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, err.Error(), nil)
+ go agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
+ voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
-}
-
-func (agent *Agent) waitForAdapterResponse(ctx context.Context, cancel context.CancelFunc, rpc string, ch chan *kafka.RpcResponse,
- onSuccess coreutils.ResponseCallback, onFailure coreutils.ResponseCallback, reqArgs ...interface{}) {
- defer cancel()
- var rpce *voltha.RPCEvent
- defer func() {
- if rpce != nil {
- agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
- voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
- }
- }()
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, "Response Channel Closed", nil)
- onFailure(ctx, rpc, status.Errorf(codes.Aborted, "channel-closed"), reqArgs)
- //add failure
- } else if rpcResponse.Err != nil {
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, rpcResponse.Err.Error(), nil)
- onFailure(ctx, rpc, rpcResponse.Err, reqArgs)
- //add failure
- } else {
- onSuccess(ctx, rpc, rpcResponse.Reply, reqArgs)
- }
- case <-ctx.Done():
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, ctx.Err().Error(), nil)
- onFailure(ctx, rpc, ctx.Err(), reqArgs)
- }
-}
-
-func (agent *Agent) waitForAdapterResponseAndLogDeviceUpdate(ctx context.Context, cancel context.CancelFunc, rpc string, ch chan *kafka.RpcResponse,
- onSuccess coreutils.ResponseCallback, onFailure coreutils.ResponseCallback, prevState *common.AdminState_Types, reqArgs ...interface{}) {
- defer cancel()
- var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
- defer func() {
- currAdminState := prevState
- if d, _ := agent.getDeviceReadOnly(ctx); d != nil {
- currAdminState = &d.AdminState
- }
- agent.logDeviceUpdate(ctx, rpc, prevState, currAdminState, operStatus, &desc)
- }()
- var rpce *voltha.RPCEvent
- defer func() {
- if rpce != nil {
- agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
- voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
- }
- }()
-
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, "Response Channel Closed", nil)
- onFailure(ctx, rpc, status.Errorf(codes.Aborted, "channel-closed"), reqArgs)
- //add failure
- } else if rpcResponse.Err != nil {
- desc = rpcResponse.Err.Error()
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, desc, nil)
- onFailure(ctx, rpc, rpcResponse.Err, reqArgs)
- //add failure
- } else {
- operStatus.Code = common.OperationResp_OPERATION_SUCCESS
- onSuccess(ctx, rpc, rpcResponse.Reply, reqArgs)
- }
- case <-ctx.Done():
- desc = ctx.Err().Error()
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, desc, nil)
- onFailure(ctx, rpc, ctx.Err(), reqArgs)
- }
+ // Log the device update event
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ desc := "adapter-response"
+ agent.logDeviceUpdate(ctx, prevState, currState, requestStatus, err, desc)
}
// getDeviceReadOnly returns a device which MUST NOT be modified, but is safe to keep forever.
@@ -390,117 +326,128 @@
return proto.Clone(agent.device).(*voltha.Device)
}
+func (agent *Agent) updateDeviceTypeAndEndpoint(ctx context.Context) error {
+ if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ return err
+ }
+ changed := false
+ cloned := agent.cloneDeviceWithoutLock()
+ if cloned.Type == "" {
+ adapterType, err := agent.adapterMgr.GetAdapterType(cloned.Type)
+ if err != nil {
+ agent.requestQueue.RequestComplete()
+ return err
+ }
+ cloned.Type = adapterType
+ changed = true
+ }
+
+ if cloned.AdapterEndpoint == "" {
+ var err error
+ if cloned.AdapterEndpoint, err = agent.adapterMgr.GetAdapterEndpoint(ctx, cloned.Id, cloned.Type); err != nil {
+ agent.requestQueue.RequestComplete()
+ return err
+ }
+ agent.adapterEndpoint = cloned.AdapterEndpoint
+ changed = true
+ }
+
+ if changed {
+ return agent.updateDeviceAndReleaseLock(ctx, cloned)
+ }
+ agent.requestQueue.RequestComplete()
+ return nil
+}
+
// enableDevice activates a preprovisioned or a disable device
func (agent *Agent) enableDevice(ctx context.Context) error {
//To preserve and use oldDevice state as prev state in new device
+ var err error
var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ var prevAdminState, currAdminState common.AdminState_Types
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
- defer agent.logDeviceUpdate(ctx, "enableDevice", nil, nil, operStatus, &desc)
+ defer func() { agent.logDeviceUpdate(ctx, &prevAdminState, &currAdminState, requestStatus, err, desc) }()
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
logger.Debugw(ctx, "enable-device", log.Fields{"device-id": agent.deviceID})
- prevDeviceState := agent.device.AdminState
-
oldDevice := agent.getDeviceReadOnlyWithoutLock()
+ prevAdminState = oldDevice.AdminState
if !agent.proceedWithRequest(oldDevice) {
agent.requestQueue.RequestComplete()
-
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconcile is in progress/failed.", agent.deviceID)
- return status.Error(codes.FailedPrecondition, desc)
+ err = status.Errorf(codes.FailedPrecondition, "cannot complete operation as device deletion is in progress or reconciling is in progress/failed: %s", agent.deviceID)
+ return err
}
if oldDevice.AdminState == voltha.AdminState_ENABLED {
logger.Warnw(ctx, "device-already-enabled", log.Fields{"device-id": agent.deviceID})
agent.requestQueue.RequestComplete()
- desc = fmt.Sprintf("cannot-enable-an-already-enabled-device: %s", oldDevice.Id)
- return status.Error(codes.FailedPrecondition, desc)
- }
-
- // First figure out which adapter will handle this device type. We do it at this stage as allow devices to be
- // pre-provisioned with the required adapter not registered. At this stage, since we need to communicate
- // with the adapter then we need to know the adapter that will handle this request
- adapterName, err := agent.adapterMgr.GetAdapterType(oldDevice.Type)
- if err != nil {
- agent.requestQueue.RequestComplete()
- desc = err.Error()
+ err = status.Errorf(codes.FailedPrecondition, fmt.Sprintf("cannot-enable-an-already-enabled-device: %s", oldDevice.Id))
return err
}
+ // Verify whether there is a device type that supports this device type
+ _, err = agent.adapterMgr.GetAdapterType(oldDevice.Type)
+ if err != nil {
+ agent.requestQueue.RequestComplete()
+ return err
+ }
+
+ // Update device adapter endpoint if not set. This is set once by the Core and use as is by the adapters. E.g if this is a
+ // child device then the parent adapter will use this device's adapter endpoint (set here) to communicate with it.
newDevice := agent.cloneDeviceWithoutLock()
- newDevice.Adapter = adapterName
+ if newDevice.AdapterEndpoint == "" {
+ if newDevice.AdapterEndpoint, err = agent.adapterMgr.GetAdapterEndpoint(ctx, newDevice.Id, newDevice.Type); err != nil {
+ agent.requestQueue.RequestComplete()
+ return err
+ }
+ agent.adapterEndpoint = newDevice.AdapterEndpoint
+ }
// Update the Admin State and set the operational state to activating before sending the request to the Adapters
newDevice.AdminState = voltha.AdminState_ENABLED
newDevice.OperStatus = voltha.OperStatus_ACTIVATING
- if err := agent.updateDeviceAndReleaseLock(ctx, newDevice); err != nil {
- desc = err.Error()
- return err
- }
-
// Adopt the device if it was in pre-provision state. In all other cases, try to re-enable it.
- var ch chan *kafka.RpcResponse
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
- subCtx = coreutils.WithFromTopicMetadataFromContext(subCtx, ctx)
-
- if oldDevice.AdminState == voltha.AdminState_PREPROVISIONED {
- ch, err = agent.adapterProxy.AdoptDevice(subCtx, newDevice)
- } else {
- ch, err = agent.adapterProxy.ReEnableDevice(subCtx, newDevice)
- }
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- cancel()
- desc = err.Error()
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": newDevice.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return err
}
-
- operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
-
- // Wait for response
- go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "enableDevice", ch, agent.onSuccess, agent.onFailure, &prevDeviceState)
- return nil
-}
-
-func (agent *Agent) waitForAdapterFlowResponse(ctx context.Context, cancel context.CancelFunc, rpc string, ch chan *kafka.RpcResponse, response coreutils.Response) {
- defer cancel()
- var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
- defer agent.logDeviceUpdate(ctx, rpc, nil, nil, operStatus, &desc)
-
- var rpce *voltha.RPCEvent
- defer func() {
- if rpce != nil {
- agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
- voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ requestStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ var err error
+ if oldDevice.AdminState == voltha.AdminState_PREPROVISIONED {
+ _, err = client.AdoptDevice(subCtx, newDevice)
+ } else {
+ _, err = client.ReEnableDevice(subCtx, newDevice)
+ }
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
}
}()
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- //add failure
- desc = "Response Channel Closed"
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, "Response Channel Closed", nil)
- response.Error(status.Errorf(codes.Aborted, "channel-closed"))
- } else if rpcResponse.Err != nil {
- //add failure
- desc = rpcResponse.Err.Error()
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, desc, nil)
- response.Error(rpcResponse.Err)
- } else {
- operStatus.Code = common.OperationResp_OPERATION_SUCCESS
- response.Done()
- }
- case <-ctx.Done():
- desc = ctx.Err().Error()
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, desc, nil)
- response.Error(ctx.Err())
+
+ // Update device
+ if err = agent.updateDeviceAndReleaseLock(ctx, newDevice); err != nil {
+ return err
}
+ currAdminState = newDevice.AdminState
+ return nil
}
//addFlowsAndGroups adds the "newFlows" and "newGroups" from the existing flows/groups and sends the update to the
@@ -516,8 +463,8 @@
if grpResponse, err = agent.addGroupsToAdapter(ctx, newGroups, flowMetadata); err != nil {
return err
}
- if errs := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, flwResponse, grpResponse); errs != nil {
- logger.Warnw(ctx, "no-adapter-response", log.Fields{"device-id": agent.deviceID, "result": errs})
+ if errs := coreutils.WaitForNilOrErrorResponses(agent.rpcTimeout, flwResponse, grpResponse); errs != nil {
+ logger.Warnw(ctx, "adapter-response", log.Fields{"device-id": agent.deviceID, "result": errs})
return status.Errorf(codes.Aborted, "flow-failure-device-%s", agent.deviceID)
}
return nil
@@ -535,7 +482,7 @@
return err
}
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, flwResponse, grpResponse); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.rpcTimeout, flwResponse, grpResponse); res != nil {
return status.Errorf(codes.Aborted, "errors-%s", res)
}
return nil
@@ -553,7 +500,7 @@
return err
}
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, flwResponse, grpResponse); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.rpcTimeout, flwResponse, grpResponse); res != nil {
return status.Errorf(codes.Aborted, "errors-%s", res)
}
return nil
@@ -561,73 +508,81 @@
//disableDevice disable a device
func (agent *Agent) disableDevice(ctx context.Context) error {
+ var err error
var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ var prevAdminState, currAdminState common.AdminState_Types
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, &prevAdminState, &currAdminState, requestStatus, err, desc) }()
- prevDeviceState := agent.device.AdminState
-
- defer agent.logDeviceUpdate(ctx, "disableDevice", nil, nil, operStatus, &desc)
-
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- desc = err.Error()
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
logger.Debugw(ctx, "disable-device", log.Fields{"device-id": agent.deviceID})
cloned := agent.cloneDeviceWithoutLock()
+ prevAdminState = agent.device.AdminState
if !agent.proceedWithRequest(cloned) {
+ err = status.Errorf(codes.FailedPrecondition, "cannot complete operation as device deletion is in progress or reconciling is in progress/failed: %s", agent.deviceID)
agent.requestQueue.RequestComplete()
- desc = fmt.Sprintf("deviceId:%s,Cannot complete operation as device deletion is in progress or reconciling is in progress/failed.", agent.deviceID)
- return status.Errorf(codes.FailedPrecondition, desc)
+ return err
}
if cloned.AdminState == voltha.AdminState_DISABLED {
desc = "device-already-disabled"
- logger.Debugw(ctx, "device-already-disabled", log.Fields{"device-id": agent.deviceID})
agent.requestQueue.RequestComplete()
return nil
}
if cloned.AdminState == voltha.AdminState_PREPROVISIONED {
agent.requestQueue.RequestComplete()
- desc = fmt.Sprintf("deviceId:%s, invalid-admin-state:%s", agent.deviceID, cloned.AdminState)
- return status.Errorf(codes.FailedPrecondition, "deviceId:%s, invalid-admin-state:%s", agent.deviceID, cloned.AdminState)
+ err = status.Errorf(codes.FailedPrecondition, "deviceId:%s, invalid-admin-state:%s", agent.deviceID, cloned.AdminState)
+ return err
}
// Update the Admin State and operational state before sending the request out
cloned.AdminState = voltha.AdminState_DISABLED
cloned.OperStatus = voltha.OperStatus_UNKNOWN
- if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
- return err
- }
-
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.DisableDevice(subCtx, cloned)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- cancel()
- desc = err.Error()
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return err
}
- operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ requestStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ _, err := client.DisableDevice(subCtx, cloned)
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
+ }
+ }()
- // Wait for response
- go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "disableDevice", ch, agent.onSuccess, agent.onFailure, &prevDeviceState)
+ // Update device
+ if err = agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
+ return err
+ }
+ currAdminState = cloned.AdminState
return nil
}
func (agent *Agent) rebootDevice(ctx context.Context) error {
var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ var err error
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
- prevDeviceState := agent.device.AdminState
-
- defer agent.logDeviceUpdate(ctx, "rebootDevice", nil, nil, operStatus, &desc)
-
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
desc = err.Error()
return err
}
@@ -637,22 +592,32 @@
device := agent.getDeviceReadOnlyWithoutLock()
if !agent.proceedWithRequest(device) {
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed.", agent.deviceID)
- return status.Errorf(codes.FailedPrecondition, desc)
- }
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.RebootDevice(subCtx, device)
- if err != nil {
- cancel()
- desc = err.Error()
+ err = status.Errorf(codes.FailedPrecondition, "cannot complete operation as device deletion is in progress or reconciling is in progress/failed:%s", agent.deviceID)
return err
}
- operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- // Wait for response
- go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "rebootDevice", ch, agent.onSuccess, agent.onFailure, &prevDeviceState)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
+ return err
+ }
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ requestStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ _, err := client.RebootDevice(subCtx, device)
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
+ }
+ }()
return nil
}
@@ -660,50 +625,54 @@
logger.Debugw(ctx, "delete-device-force", log.Fields{"device-id": agent.deviceID})
var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ var err error
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "deleteDeviceForce", nil, nil, operStatus, &desc)
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
// Get the device Transient state, return err if it is DELETING
previousDeviceTransientState := agent.getTransientState()
-
- if agent.isStateDeleting(previousDeviceTransientState) {
- agent.requestQueue.RequestComplete()
- desc = fmt.Sprintf("deviceId:%s, Device Deletion is in progress",
- agent.deviceID)
- agent.logDeviceUpdate(ctx, "deleteDeviceForce", nil, nil, operStatus, &desc)
- return status.Error(codes.FailedPrecondition, desc)
- }
-
- //Send stop Reconcile if in progress
- agent.stopReconcile()
-
device := agent.cloneDeviceWithoutLock()
- if err := agent.updateDeviceWithTransientStateAndReleaseLock(ctx, device,
- voltha.DeviceTransientState_FORCE_DELETING, previousDeviceTransientState); err != nil {
+ if !agent.isForceDeletingAllowed(previousDeviceTransientState, device) {
+ agent.requestQueue.RequestComplete()
+ err = status.Error(codes.FailedPrecondition, fmt.Sprintf("deviceId:%s, force deletion is in progress", agent.deviceID))
return err
}
- previousAdminState := device.AdminState
- if previousAdminState != ic.AdminState_PREPROVISIONED {
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
- ch, err := agent.adapterProxy.DeleteDevice(subCtx, device)
+ previousAdminState := device.AdminState
+ if previousAdminState != common.AdminState_PREPROVISIONED {
+ var client adapter_services.AdapterServiceClient
+ client, err = agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "deleteDeviceForce", nil, nil, operStatus, &desc)
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return err
}
- // As force delete will not be dependent over the response of adapter, marking this operation as success
- operStatus.Code = common.OperationResp_OPERATION_SUCCESS
- agent.logDeviceUpdate(ctx, "deleteDeviceForce", nil, nil, operStatus, &desc)
- // Since it is a case of force delete, nothing needs to be done on adapter responses.
- go agent.waitForAdapterForceDeleteResponse(subCtx, cancel, "deleteDeviceForce", ch, agent.onSuccess,
- agent.onFailure)
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ requestStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ _, err := client.DeleteDevice(subCtx, device)
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
+ }
+ }()
+ }
+
+ // Update device
+ if err = agent.updateDeviceWithTransientStateAndReleaseLock(ctx, device,
+ core.DeviceTransientState_FORCE_DELETING, previousDeviceTransientState); err != nil {
+ return err
}
return nil
}
@@ -712,12 +681,11 @@
logger.Debugw(ctx, "delete-device", log.Fields{"device-id": agent.deviceID})
var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
- prevState := agent.device.AdminState
+ var err error
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
- defer agent.logDeviceUpdate(ctx, "deleteDevice", nil, nil, operStatus, &desc)
-
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
desc = err.Error()
return err
}
@@ -726,8 +694,8 @@
if !agent.proceedWithRequest(device) {
agent.requestQueue.RequestComplete()
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", agent.deviceID)
- return status.Error(codes.FailedPrecondition, desc)
+ err = status.Errorf(codes.FailedPrecondition, "cannot complete operation as device deletion is in progress or reconciling is in progress/failed: %s", agent.deviceID)
+ return err
}
// Get the device Transient state, return err if it is DELETING
@@ -735,38 +703,48 @@
previousAdminState := device.AdminState
// Change the device transient state to DELETING_FROM_ADAPTER state till the device is removed from adapters.
- currentDeviceTransientState := voltha.DeviceTransientState_DELETING_FROM_ADAPTER
+ currentDeviceTransientState := core.DeviceTransientState_DELETING_FROM_ADAPTER
- if previousAdminState == ic.AdminState_PREPROVISIONED {
+ if previousAdminState == common.AdminState_PREPROVISIONED {
// Change the state to DELETING POST ADAPTER RESPONSE directly as adapters have no info of the device.
- currentDeviceTransientState = voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE
+ currentDeviceTransientState = core.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE
}
- if err := agent.updateDeviceWithTransientStateAndReleaseLock(ctx, device,
+ // If the device was in pre-prov state (only parent device are in that state) then do not send the request to the
+ // adapter
+ if previousAdminState != common.AdminState_PREPROVISIONED {
+ var client adapter_services.AdapterServiceClient
+ client, err = agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
+ return err
+ }
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ requestStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ _, err := client.DeleteDevice(subCtx, device)
+ if err == nil {
+ agent.onDeleteSuccess(subCtx, nil, nil)
+ } else {
+ agent.onDeleteFailure(subCtx, err, nil, nil)
+ }
+ }()
+ }
+
+ // Update device and release lock
+ if err = agent.updateDeviceWithTransientStateAndReleaseLock(ctx, device,
currentDeviceTransientState, previousDeviceTransientState); err != nil {
desc = err.Error()
return err
}
- // If the device was in pre-prov state (only parent device are in that state) then do not send the request to the
- // adapter
- if previousAdminState != ic.AdminState_PREPROVISIONED {
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
- ch, err := agent.adapterProxy.DeleteDevice(subCtx, device)
- if err != nil {
- cancel()
- //updating of transient state is required in error
- if err := agent.updateTransientState(ctx, voltha.DeviceTransientState_DELETE_FAILED); err != nil {
- logger.Errorw(ctx, "failed-to-update-transient-state-as-delete-failed", log.Fields{"device-id": agent.deviceID})
- }
- desc = err.Error()
- return err
- }
-
- operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "deleteDevice", ch, agent.onDeleteSuccess,
- agent.onDeleteFailure, &prevState)
- }
return nil
}
@@ -789,67 +767,66 @@
if err != nil {
return nil, err
}
- ch, err := agent.adapterProxy.GetOfpDeviceInfo(ctx, device)
+
+ // Get the gRPC client
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
return nil, err
}
- // Wait for adapter response
- rpcResponse, ok := <-ch
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed")
- }
- if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
- }
- // Successful response
- switchCap := &ic.SwitchCapability{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, switchCap); err != nil {
- return nil, err
- }
- return switchCap, nil
+ return client.GetOfpDeviceInfo(ctx, device)
}
-func (agent *Agent) onPacketFailure(ctx context.Context, rpc string, response interface{}, args ...interface{}) {
- // packet data is encoded in the args param as the first parameter
- var packet []byte
- if len(args) >= 1 {
- if pkt, ok := args[0].([]byte); ok {
- packet = pkt
- }
- }
- var errResp error
- if err, ok := response.(error); ok {
- errResp = err
- }
- logger.Warnw(ctx, "packet-out-error", log.Fields{
+func (agent *Agent) onPacketFailure(ctx context.Context, err error, packet *ofp.OfpPacketOut) {
+ logger.Errorw(ctx, "packet-out-error", log.Fields{
"device-id": agent.deviceID,
- "error": errResp,
- "packet": hex.EncodeToString(packet),
+ "error": err.Error(),
+ "packet": hex.EncodeToString(packet.Data),
})
+ rpce := agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, err.Error(), nil)
+ go agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
+ voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
}
func (agent *Agent) packetOut(ctx context.Context, outPort uint32, packet *ofp.OfpPacketOut) error {
- // If deviceType=="" then we must have taken ownership of this device.
- // Fixes VOL-2226 where a core would take ownership and have stale data
if agent.deviceType == "" {
agent.reconcileWithKVStore(ctx)
}
// Send packet to adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.PacketOut(subCtx, agent.deviceType, agent.deviceID, outPort, packet)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- cancel()
- return nil
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ })
+ return err
}
- go agent.waitForAdapterResponse(subCtx, cancel, "packetOut", ch, agent.onSuccess, agent.onPacketFailure, packet.Data)
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ go func() {
+ defer cancel()
+ _, err := client.SendPacketOut(subCtx, &ic.PacketOut{
+ DeviceId: agent.deviceID,
+ EgressPortNo: outPort,
+ Packet: packet,
+ })
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, false)
+ } else {
+ agent.onPacketFailure(subCtx, err, packet)
+ }
+ }()
return nil
}
func (agent *Agent) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
logger.Debugw(ctx, "update-device-using-adapter-data", log.Fields{"device-id": device.Id})
@@ -863,27 +840,40 @@
cloned.Vlan = device.Vlan
cloned.Reason = device.Reason
cloned.ImageDownloads = device.ImageDownloads
- return agent.updateDeviceAndReleaseLock(ctx, cloned)
+ cloned.OperStatus = device.OperStatus
+ cloned.ConnectStatus = device.ConnectStatus
+ if err = agent.updateDeviceAndReleaseLock(ctx, cloned); err == nil {
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
+ }
+ return err
}
func (agent *Agent) updateDeviceStatus(ctx context.Context, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ opStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, opStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
cloned := agent.cloneDeviceWithoutLock()
// Ensure the enums passed in are valid - they will be invalid if they are not set when this function is invoked
if s, ok := voltha.ConnectStatus_Types_name[int32(connStatus)]; ok {
- logger.Debugw(ctx, "update-device-status-conn", log.Fields{"ok": ok, "val": s})
+ logger.Debugw(ctx, "update-device-conn-status", log.Fields{"ok": ok, "val": s})
cloned.ConnectStatus = connStatus
}
if s, ok := voltha.OperStatus_Types_name[int32(operStatus)]; ok {
- logger.Debugw(ctx, "update-device-status-conn", log.Fields{"ok": ok, "val": s})
+ logger.Debugw(ctx, "update-device-oper-status", log.Fields{"ok": ok, "val": s})
cloned.OperStatus = operStatus
}
logger.Debugw(ctx, "update-device-status", log.Fields{"device-id": cloned.Id, "oper-status": cloned.OperStatus, "connect-status": cloned.ConnectStatus})
// Store the device
- return agent.updateDeviceAndReleaseLock(ctx, cloned)
+ if err = agent.updateDeviceAndReleaseLock(ctx, cloned); err == nil {
+ opStatus.Code = common.OperationResp_OPERATION_SUCCESS
+ }
+ return err
}
// TODO: A generic device update by attribute
@@ -926,7 +916,12 @@
}
func (agent *Agent) simulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) error {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
defer agent.requestQueue.RequestComplete()
@@ -934,15 +929,28 @@
device := agent.getDeviceReadOnlyWithoutLock()
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.SimulateAlarm(subCtx, device, simulateReq)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- cancel()
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
return err
}
- go agent.waitForAdapterResponse(subCtx, cancel, "simulateAlarm", ch, agent.onSuccess, agent.onFailure)
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ requestStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ _, err := client.SimulateAlarm(subCtx, &ic.SimulateAlarmMessage{Device: device, Request: simulateReq})
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, false)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, false)
+ }
+ }()
return nil
}
@@ -990,7 +998,7 @@
// This function updates the device transient in the DB through loader, releases the device lock, and runs any state transitions.
// The calling function MUST hold the device lock. The caller MUST NOT modify the device after this is called.
func (agent *Agent) updateDeviceWithTransientStateAndReleaseLock(ctx context.Context, device *voltha.Device,
- transientState, prevTransientState voltha.DeviceTransientState_Types) error {
+ transientState, prevTransientState core.DeviceTransientState_Types) error {
// fail early if this agent is no longer valid
if agent.stopped {
agent.requestQueue.RequestComplete()
@@ -1004,9 +1012,10 @@
// update in db
if err := agent.dbProxy.Set(ctx, agent.deviceID, device); err != nil {
//Reverting TransientState update
- err := agent.updateTransientState(ctx, prevTransientState)
- logger.Errorw(ctx, "failed-to-revert-transient-state-update-on-error", log.Fields{"device-id": device.Id,
- "previous-transient-state": prevTransientState, "current-transient-state": transientState})
+ if errTransient := agent.updateTransientState(ctx, prevTransientState); errTransient != nil {
+ logger.Errorw(ctx, "failed-to-revert-transient-state-update-on-error", log.Fields{"device-id": device.Id,
+ "previous-transient-state": prevTransientState, "current-transient-state": transientState, "error": errTransient})
+ }
agent.requestQueue.RequestComplete()
return status.Errorf(codes.Internal, "failed-update-device:%s: %s", agent.deviceID, err)
}
@@ -1023,44 +1032,47 @@
// release lock before processing transition
agent.requestQueue.RequestComplete()
- subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
- if err := agent.deviceMgr.stateTransitions.ProcessTransition(subCtx,
- device, prevDevice, transientState, prevTransientState); err != nil {
- logger.Errorw(ctx, "failed-process-transition", log.Fields{"device-id": device.Id, "previous-admin-state": prevDevice.AdminState, "current-admin-state": device.AdminState})
- // Sending RPC EVENT here
- rpce := agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, err.Error(), nil)
- agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce, voltha.EventCategory_COMMUNICATION,
- nil, time.Now().Unix())
- }
+ go func() {
+ subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
+ if err := agent.deviceMgr.stateTransitions.ProcessTransition(subCtx,
+ device, prevDevice, transientState, prevTransientState); err != nil {
+ logger.Errorw(ctx, "failed-process-transition", log.Fields{"device-id": device.Id, "previous-admin-state": prevDevice.AdminState, "current-admin-state": device.AdminState})
+ // Sending RPC EVENT here
+ rpce := agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, err.Error(), nil)
+ agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce, voltha.EventCategory_COMMUNICATION,
+ nil, time.Now().Unix())
+ }
+ }()
return nil
}
func (agent *Agent) updateDeviceReason(ctx context.Context, reason string) error {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ logger.Debugw(ctx, "update-device-reason", log.Fields{"device-id": agent.deviceID, "reason": reason})
+
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
- logger.Debugw(ctx, "update-device-reason", log.Fields{"device-id": agent.deviceID, "reason": reason})
-
- var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
-
- defer agent.logDeviceUpdate(ctx, "updateDeviceReason", nil, nil, operStatus, &desc)
-
cloned := agent.cloneDeviceWithoutLock()
cloned.Reason = reason
- retErr := agent.updateDeviceAndReleaseLock(ctx, cloned)
- if retErr != nil {
- desc = retErr.Error()
- } else {
- operStatus.Code = common.OperationResp_OPERATION_SUCCESS
- desc = reason
+ if err = agent.updateDeviceAndReleaseLock(ctx, cloned); err == nil {
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
}
- return retErr
+ return err
}
func (agent *Agent) ChildDeviceLost(ctx context.Context, device *voltha.Device) error {
logger.Debugw(ctx, "child-device-lost", log.Fields{"child-device-id": device.Id, "parent-device-id": agent.deviceID})
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
// Remove the associated peer ports on the parent device
for portID := range agent.portLoader.ListIDs() {
if portHandle, have := agent.portLoader.Lock(portID); have {
@@ -1082,154 +1094,199 @@
}
//send request to adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.ChildDeviceLost(ctx, agent.deviceType, device)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- cancel()
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
return err
}
- go agent.waitForAdapterResponse(subCtx, cancel, "childDeviceLost", ch, agent.onSuccess, agent.onFailure)
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
+ requestStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ _, err := client.ChildDeviceLost(subCtx, device)
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
+ }
+ }()
return nil
}
func (agent *Agent) startOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- return nil, err
- }
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
- cloned := agent.cloneDeviceWithoutLock()
-
- if cloned.Adapter == "" {
- adapterName, err := agent.adapterMgr.GetAdapterType(cloned.Type)
- if err != nil {
- agent.requestQueue.RequestComplete()
- return nil, err
- }
- cloned.Adapter = adapterName
- }
-
- // Send request to the adapter
- ch, err := agent.adapterProxy.StartOmciTest(ctx, cloned, omcitestrequest)
- agent.requestQueue.RequestComplete()
+ // OMCI test may be performed on a pre-provisioned device. If a device is in that state both its device type and endpoint
+ // may not have been set yet.
+ // First check if we need to update the type or endpoint
+ cloned, err := agent.getDeviceReadOnly(ctx)
if err != nil {
return nil, err
}
-
- // Wait for the adapter response
- rpcResponse, ok := <-ch
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
- }
- if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
+ if cloned.Type == "" || cloned.AdapterEndpoint == "" {
+ if err = agent.updateDeviceTypeAndEndpoint(ctx); err != nil {
+ return nil, err
+ }
+ cloned, err = agent.getDeviceReadOnly(ctx)
+ if err != nil {
+ return nil, err
+ }
}
- // Unmarshal and return the response
- testResp := &voltha.TestResponse{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, testResp); err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "%s", err.Error())
+ // Send request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ return nil, err
}
- logger.Debugw(ctx, "omci_test_request-success-device-agent", log.Fields{"test-resp": testResp})
- return testResp, nil
+
+ res, err := client.StartOmciTest(ctx, &ic.OMCITest{
+ Device: cloned,
+ Request: omcitestrequest,
+ })
+ if err == nil {
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
+ }
+ return res, err
}
func (agent *Agent) getExtValue(ctx context.Context, pdevice *voltha.Device, cdevice *voltha.Device, valueparam *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
logger.Debugw(ctx, "get-ext-value", log.Fields{"device-id": agent.deviceID, "onu-id": valueparam.Id, "value-type": valueparam.Value})
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
- //send request to adapter
- ch, err := agent.adapterProxy.GetExtValue(ctx, pdevice, cdevice, valueparam.Id, valueparam.Value)
- agent.requestQueue.RequestComplete()
+ //send request to adapter synchronously
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, pdevice.AdapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": pdevice.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
- // Wait for the adapter response
- rpcResponse, ok := <-ch
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
- }
- if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
- }
+ // Release lock before sending to adapter
+ agent.requestQueue.RequestComplete()
- // Unmarshal and return the response
- Resp := &voltha.ReturnValues{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, Resp); err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "%s", err.Error())
+ retVal, err := client.GetExtValue(ctx, &ic.GetExtValueMessage{
+ ParentDevice: pdevice,
+ ChildDevice: cdevice,
+ ValueType: valueparam.Value,
+ })
+ if err == nil {
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
}
- logger.Debugw(ctx, "get-ext-value-success-device-agent", log.Fields{"Resp": Resp})
- return Resp, nil
+ return retVal, err
}
func (agent *Agent) setExtValue(ctx context.Context, device *voltha.Device, value *voltha.ValueSet) (*empty.Empty, error) {
logger.Debugw(ctx, "set-ext-value", log.Fields{"device-id": value.Id})
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
//send request to adapter
- ch, err := agent.adapterProxy.SetExtValue(ctx, device, value)
- agent.requestQueue.RequestComplete()
+ //send request to adapter synchronously
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
+ // Release lock before sending request to adapter
+ agent.requestQueue.RequestComplete()
- // Wait for the adapter response
- rpcResponse, ok := <-ch
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
+ retVal, err := client.SetExtValue(ctx, &ic.SetExtValueMessage{
+ Device: device,
+ Value: value,
+ })
+ if err == nil {
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
}
- if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
- }
-
- // Unmarshal and return the response
- logger.Debug(ctx, "set-ext-value-success-device-agent")
- return &empty.Empty{}, nil
+ return retVal, err
}
func (agent *Agent) getSingleValue(ctx context.Context, request *extension.SingleGetValueRequest) (*extension.SingleGetValueResponse, error) {
logger.Debugw(ctx, "get-single-value", log.Fields{"device-id": request.TargetId})
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
cloned := agent.cloneDeviceWithoutLock()
//send request to adapter
- ch, err := agent.adapterProxy.GetSingleValue(ctx, cloned.Adapter, request)
- agent.requestQueue.RequestComplete()
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": cloned.Id,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
+ // Release lock before sending request to adapter
+ agent.requestQueue.RequestComplete()
- // Wait for the adapter response
- rpcResponse, ok := <-ch
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
+ resp, err := client.GetSingleValue(ctx, request)
+ if err == nil {
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
}
-
- if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
- }
-
- resp := &extension.SingleGetValueResponse{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, resp); err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "%s", err.Error())
- }
-
- return resp, nil
+ return resp, err
}
func (agent *Agent) setSingleValue(ctx context.Context, request *extension.SingleSetValueRequest) (*extension.SingleSetValueResponse, error) {
logger.Debugw(ctx, "set-single-value", log.Fields{"device-id": request.TargetId})
+ var err error
+ var desc string
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc) }()
+
if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
@@ -1237,28 +1294,26 @@
cloned := agent.cloneDeviceWithoutLock()
//send request to adapter
- ch, err := agent.adapterProxy.SetSingleValue(ctx, cloned.Adapter, request)
- agent.requestQueue.RequestComplete()
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
+ // Release lock before sending request to adapter
+ agent.requestQueue.RequestComplete()
- // Wait for the adapter response
- rpcResponse, ok := <-ch
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-cloned-id-%s", agent.deviceID)
+ resp, err := client.SetSingleValue(ctx, request)
+ if err == nil {
+ requestStatus.Code = common.OperationResp_OPERATION_SUCCESS
}
-
- if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
- }
-
- resp := &extension.SingleSetValueResponse{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, resp); err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "%s", err.Error())
- }
-
- return resp, nil
+ return resp, err
}
func (agent *Agent) proceedWithRequest(device *voltha.Device) bool {
@@ -1273,32 +1328,66 @@
agent.stopReconcilingMutex.Unlock()
}
-func (agent *Agent) ReconcileDevice(ctx context.Context, device *voltha.Device) {
+// abortAllProcessing is invoked when an adapter managing this device is restarted
+func (agent *Agent) abortAllProcessing(ctx context.Context) error {
+ logger.Infow(ctx, "aborting-current-running-requests", log.Fields{"device-id": agent.deviceID})
+ if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ return err
+ }
+ defer agent.requestQueue.RequestComplete()
+
+ // If any reconciling is in progress just abort it. The adapter is gone.
+ agent.stopReconcile()
+
+ // Update the Core device transient state accordingly
+ var updatedState core.DeviceTransientState_Types
+ switch agent.getTransientState() {
+ case core.DeviceTransientState_RECONCILE_IN_PROGRESS:
+ updatedState = core.DeviceTransientState_NONE
+ case core.DeviceTransientState_FORCE_DELETING:
+ updatedState = core.DeviceTransientState_DELETE_FAILED
+ case core.DeviceTransientState_DELETING_FROM_ADAPTER:
+ updatedState = core.DeviceTransientState_DELETE_FAILED
+ default:
+ updatedState = core.DeviceTransientState_NONE
+ }
+ if err := agent.updateTransientState(ctx, updatedState); err != nil {
+ logger.Errorf(ctx, "transient-state-update-failed", log.Fields{"error": err})
+ return err
+ }
+ return nil
+}
+
+func (agent *Agent) ReconcileDevice(ctx context.Context) {
+ requestStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc)
+ return
+ }
+
+ device := agent.getDeviceReadOnlyWithoutLock()
+ if device.AdminState == voltha.AdminState_PREPROVISIONED {
+ agent.requestQueue.RequestComplete()
+ logger.Debugw(ctx, "device-in-preprovisioning-state-reconcile-not-needed", log.Fields{"device-id": device.Id})
return
}
if !agent.proceedWithRequest(device) {
agent.requestQueue.RequestComplete()
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", device.Id)
- logger.Errorf(ctx, desc)
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ err := fmt.Errorf("cannot complete operation as device deletion/reconciling is in progress or reconcile failed for device : %s", device.Id)
+ logger.Errorw(ctx, "reconcile-failed", log.Fields{"error": err})
+ agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc)
return
}
//set transient state to RECONCILE IN PROGRESS
- err := agent.updateTransientState(ctx, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ err := agent.updateTransientState(ctx, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
if err != nil {
agent.requestQueue.RequestComplete()
- desc = fmt.Sprintf("Not able to set device transient state to Reconcile in progress."+
- "Err: %s", err.Error())
- logger.Errorf(ctx, desc)
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ logger.Errorw(ctx, "setting-transient-state-failed", log.Fields{"error": err})
+ agent.logDeviceUpdate(ctx, nil, nil, requestStatus, nil, desc)
return
}
@@ -1343,43 +1432,35 @@
backoffTimer = time.NewTimer(duration)
- logger.Debugw(ctx, "retrying-reconciling", log.Fields{"deviceID": device.Id})
- // Send a reconcile request to the adapter.
- ch, err := agent.adapterProxy.ReconcileDevice(ctx, agent.device)
- //release lock before moving further
+ logger.Debugw(ctx, "retrying-reconciling", log.Fields{"deviceID": device.Id, "endpoint": device.AdapterEndpoint})
+ // Release lock before sending request to adapter
agent.requestQueue.RequestComplete()
+
+ // Send a reconcile request to the adapter.
+ err := agent.sendReconcileRequestToAdapter(ctx, device)
+ if errors.Is(err, errContextExpired) || errors.Is(err, errReconcileAborted) {
+ logger.Errorw(ctx, "reconcile-aborted", log.Fields{"error": err})
+ requestStatus = &common.OperationResp{Code: common.OperationResp_OperationReturnCode(common.OperStatus_FAILED)}
+ desc = "aborted"
+ agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc)
+ break retry
+ }
if err != nil {
- desc := fmt.Sprintf("Failed reconciling from adapter side. Err: %s", err.Error())
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc)
<-backoffTimer.C
// backoffTimer expired continue
// Take lock back before retrying
if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc)
break retry
}
continue
}
-
- // if return err retry if not then break loop and quit retrying reconcile
- if err = agent.waitForReconcileResponse(backoffTimer, ch); err != nil {
- desc = err.Error()
- logger.Errorf(ctx, desc)
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
- <-backoffTimer.C
- } else {
- operStatus = &common.OperationResp{Code: common.OperationResp_OPERATION_IN_PROGRESS}
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
- break retry
- }
-
- // Take lock back before retrying
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
- break retry
- }
+ // Success
+ requestStatus = &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
+ desc = "adapter-response"
+ agent.logDeviceUpdate(ctx, nil, nil, requestStatus, err, desc)
+ break retry
}
// Retry loop is broken, so stop any timers and drain the channel
@@ -1400,18 +1481,23 @@
}
}
-func (agent *Agent) waitForReconcileResponse(backoffTimer *time.Timer, ch chan *kafka.RpcResponse) error {
+func (agent *Agent) sendReconcileRequestToAdapter(ctx context.Context, device *voltha.Device) error {
+ logger.Debugw(ctx, "sending-reconcile-to-adapter", log.Fields{"device-id": device.Id, "endpoint": agent.adapterEndpoint})
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ return err
+ }
+ adapterResponse := make(chan error)
+ go func() {
+ _, err := client.ReconcileDevice(ctx, device)
+ adapterResponse <- err
+ }()
select {
// wait for response
- case resp, ok := <-ch:
- if !ok {
- //channel-closed
- return errors.New("channel on which reconcile response is awaited is closed")
- } else if resp.Err != nil {
- //error encountered
- return fmt.Errorf("error encountered while retrying reconcile. Err: %s", resp.Err.Error())
+ case err := <-adapterResponse:
+ if err != nil {
+ return err
}
-
//In case of success quit retrying and wait for adapter to reset operation state of device
agent.stopReconcilingMutex.Lock()
agent.stopReconciling = nil
@@ -1425,33 +1511,47 @@
agent.stopReconcilingMutex.Unlock()
if !ok {
//channel-closed
- return errors.New("channel used to notify to stop reconcile is closed")
+ return fmt.Errorf("reconcile channel closed:%w", errReconcileAborted)
}
- return nil
- //continue if timer expired
- case <-backoffTimer.C:
+ return fmt.Errorf("reconciling aborted:%w", errReconcileAborted)
+ // Context expired
+ case <-ctx.Done():
+ return fmt.Errorf("context expired:%s :%w", ctx.Err(), errContextExpired)
}
- return nil
}
func (agent *Agent) reconcilingCleanup(ctx context.Context) error {
var desc string
+ var err error
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ desc = "reconcile-cleanup-failed"
return err
}
defer agent.requestQueue.RequestComplete()
- err := agent.updateTransientState(ctx, voltha.DeviceTransientState_NONE)
+ err = agent.updateTransientState(ctx, core.DeviceTransientState_NONE)
if err != nil {
- desc = fmt.Sprintf("Not able to clear device transient state from Reconcile in progress."+
- "Err: %s", err.Error())
- logger.Errorf(ctx, desc)
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ logger.Errorf(ctx, "transient-state-update-failed", log.Fields{"error": err})
return err
}
- operStatus = &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
- agent.logDeviceUpdate(ctx, "Reconciling", nil, nil, operStatus, &desc)
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return nil
}
+
+func (agent *Agent) isAdapterConnectionUp(ctx context.Context) bool {
+ c, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ return c != nil && err == nil
+}
+
+func (agent *Agent) canDeviceRequestProceed(ctx context.Context) error {
+ if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ return err
+ }
+ defer agent.requestQueue.RequestComplete()
+ if agent.proceedWithRequest(agent.device) {
+ return nil
+ }
+ return fmt.Errorf("device-cannot-process-request-%s", agent.deviceID)
+}
diff --git a/rw_core/core/device/agent_device_update.go b/rw_core/core/device/agent_device_update.go
index a4f2986..599c2cf 100644
--- a/rw_core/core/device/agent_device_update.go
+++ b/rw_core/core/device/agent_device_update.go
@@ -19,23 +19,31 @@
import (
"context"
"fmt"
+
"github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/common"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
)
-func (agent *Agent) logDeviceUpdate(ctx context.Context, operation string, prevState *common.AdminState_Types, currState *common.AdminState_Types, status *common.OperationResp, desc *string) {
- logger.Debugw(ctx, "addDeviceUpdate", log.Fields{"device-id": agent.deviceID})
-
- requestedBy := utils.GetFromTopicMetadataFromContext(ctx)
+func (agent *Agent) logDeviceUpdate(ctx context.Context, prevState, currState *common.AdminState_Types, status *common.OperationResp, err error, desc string) {
+ requestedBy := utils.GetEndpointMetadataFromContext(ctx)
if requestedBy == "" {
requestedBy = "NB"
}
- logger.Infow(ctx, "logDeviceUpdate", log.Fields{"device-update": operation, "device-update-id": agent.deviceID,
+ rpc := utils.GetRPCMetadataFromContext(ctx)
+
+ fields := log.Fields{"rpc": rpc, "device-id": agent.deviceID,
"requested-by": requestedBy, "state-change": agent.stateChangeString(prevState, currState),
- "status": status.GetCode().String(), "description": desc})
+ "status": status.GetCode().String(), "description": desc, "error": err}
+
+ if err != nil {
+ logger.Errorw(ctx, "logDeviceUpdate-failed", fields)
+ return
+ }
+
+ logger.Infow(ctx, "logDeviceUpdate-success", fields)
}
func (agent *Agent) stateChangeString(prevState *common.AdminState_Types, currState *common.AdminState_Types) string {
diff --git a/rw_core/core/device/agent_flow.go b/rw_core/core/device/agent_flow.go
index f13003b..6ad4488 100644
--- a/rw_core/core/device/agent_flow.go
+++ b/rw_core/core/device/agent_flow.go
@@ -20,13 +20,15 @@
"context"
"fmt"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+
"github.com/gogo/protobuf/proto"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/common"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -47,8 +49,10 @@
func (agent *Agent) addFlowsToAdapter(ctx context.Context, newFlows []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
logger.Debugw(ctx, "add-flows-to-adapters", log.Fields{"device-id": agent.deviceID, "flows": newFlows, "flow-metadata": flowMetadata})
+ var err error
var desc string
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
if (len(newFlows)) == 0 {
logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": newFlows})
@@ -56,22 +60,17 @@
}
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
}
if !agent.proceedWithRequest(device) {
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", agent.deviceID)
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return coreutils.DoneResponse(), err
}
dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
if err != nil {
- desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
+ return coreutils.DoneResponse(), err
}
flowsToAdd := make([]*ofp.OfpFlowStats, 0)
@@ -80,7 +79,6 @@
flowHandle, created, err := agent.flowCache.LockOrCreate(ctx, flow)
if err != nil {
desc = err.Error()
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
return coreutils.DoneResponse(), err
}
if created {
@@ -91,9 +89,7 @@
//Flow needs to be updated.
if err := flowHandle.Update(ctx, flow); err != nil {
flowHandle.Unlock()
- desc = fmt.Sprintf("failure-updating-flow-%d-to-device-%s", flow.Id, agent.deviceID)
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.Internal, "failure-updating-flow-%d-to-device-%s", flow.Id, agent.deviceID)
+ return coreutils.DoneResponse(), err
}
flowsToDelete = append(flowsToDelete, flowToReplace)
flowsToAdd = append(flowsToAdd, flow)
@@ -108,25 +104,21 @@
// Sanity check
if (len(flowsToAdd)) == 0 {
logger.Debugw(ctx, "no-flows-to-update", log.Fields{"device-id": agent.deviceID, "flows": newFlows})
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
// Send update to adapters
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
response := coreutils.NewResponse()
+ subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
if !dType.AcceptsAddRemoveFlowUpdates {
-
updatedAllFlows := agent.listDeviceFlows()
- rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
+ ctr, flowSlice := 0, make([]*ofp.OfpFlowStats, len(updatedAllFlows))
+ for _, flow := range updatedAllFlows {
+ flowSlice[ctr] = flow
+ ctr++
}
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "addFlowsToAdapter", rpcResponse, response)
+ go agent.sendBulkFlows(subCtx, device, &voltha.Flows{Items: flowSlice}, nil, flowMetadata, response)
} else {
flowChanges := &ofp.FlowChanges{
ToAdd: &voltha.Flows{Items: flowsToAdd},
@@ -137,55 +129,128 @@
ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
}
- rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
- }
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "addFlowsToAdapter", rpcResponse, response)
+ go agent.sendIncrementalFlows(subCtx, device, flowChanges, groupChanges, flowMetadata, response)
}
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
return response, nil
}
+func (agent *Agent) sendBulkFlows(
+ ctx context.Context,
+ device *voltha.Device,
+ flows *voltha.Flows,
+ groups *voltha.FlowGroups,
+ flowMetadata *voltha.FlowMetadata,
+ response coreutils.Response,
+) {
+ var err error
+ var desc string
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
+ // Get a grpc client
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
+ response.Error(err)
+ return
+ }
+ subCtx, cancel := context.WithTimeout(ctx, agent.rpcTimeout)
+ defer cancel()
+
+ if _, err = client.UpdateFlowsBulk(subCtx, &ic.BulkFlows{
+ Device: device,
+ Flows: flows,
+ Groups: groups,
+ FlowMetadata: flowMetadata,
+ }); err != nil {
+ response.Error(err)
+ } else {
+ response.Done()
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
+ }
+}
+
+func (agent *Agent) sendIncrementalFlows(
+ ctx context.Context,
+ device *voltha.Device,
+ flowChanges *ofp.FlowChanges,
+ groupChanges *ofp.FlowGroupChanges,
+ flowMetadata *voltha.FlowMetadata,
+ response coreutils.Response,
+) {
+ var err error
+ var desc string
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
+ // Get a grpc client
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
+ response.Error(err)
+ return
+ }
+ subCtx, cancel := context.WithTimeout(ctx, agent.rpcTimeout)
+ defer cancel()
+ if _, err = client.UpdateFlowsIncrementally(subCtx, &ic.IncrementalFlows{
+ Device: device,
+ Flows: flowChanges,
+ Groups: groupChanges,
+ FlowMetadata: flowMetadata,
+ }); err != nil {
+ response.Error(err)
+ } else {
+ response.Done()
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
+ }
+}
+
func (agent *Agent) deleteFlowsFromAdapter(ctx context.Context, flowsToDel []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
logger.Debugw(ctx, "delete-flows-from-adapter", log.Fields{"device-id": agent.deviceID, "flows": flowsToDel})
var desc string
+ var err error
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
if (len(flowsToDel)) == 0 {
logger.Debugw(ctx, "nothing-to-delete", log.Fields{"device-id": agent.deviceID, "flows": flowsToDel})
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
- defer agent.logDeviceUpdate(ctx, "deleteFlowsFromAdapter", nil, nil, operStatus, &desc)
-
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- desc = err.Error()
- return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+ return coreutils.DoneResponse(), err
}
if !agent.proceedWithRequest(device) {
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", device.Id)
- agent.logDeviceUpdate(ctx, "deleteFlowsFromAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return coreutils.DoneResponse(), err
}
dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
if err != nil {
- desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
+ return coreutils.DoneResponse(), err
}
for _, flow := range flowsToDel {
if flowHandle, have := agent.flowCache.Lock(flow.Id); have {
// Update the store and cache
- if err := flowHandle.Delete(ctx); err != nil {
+ if err = flowHandle.Delete(ctx); err != nil {
flowHandle.Unlock()
desc = err.Error()
return coreutils.DoneResponse(), err
@@ -195,20 +260,16 @@
}
// Send update to adapters
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
response := coreutils.NewResponse()
+ subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
if !dType.AcceptsAddRemoveFlowUpdates {
-
updatedAllFlows := agent.listDeviceFlows()
- rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- return coreutils.DoneResponse(), err
+ ctr, flowSlice := 0, make([]*ofp.OfpFlowStats, len(updatedAllFlows))
+ for _, flow := range updatedAllFlows {
+ flowSlice[ctr] = flow
+ ctr++
}
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteFlowToAdapter", rpcResponse, response)
+ go agent.sendBulkFlows(subCtx, device, &voltha.Flows{Items: flowSlice}, nil, flowMetadata, response)
} else {
flowChanges := &ofp.FlowChanges{
ToAdd: &voltha.Flows{Items: []*ofp.OfpFlowStats{}},
@@ -219,13 +280,7 @@
ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
}
- rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- return coreutils.DoneResponse(), err
- }
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteFlowToAdapter", rpcResponse, response)
+ go agent.sendIncrementalFlows(subCtx, device, flowChanges, groupChanges, flowMetadata, response)
}
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
return response, nil
@@ -234,37 +289,35 @@
func (agent *Agent) updateFlowsToAdapter(ctx context.Context, updatedFlows []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
logger.Debugw(ctx, "update-flows-to-adapter", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
+ var err error
var desc string
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
if (len(updatedFlows)) == 0 {
logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+ return coreutils.DoneResponse(), err
}
if !agent.proceedWithRequest(device) {
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", device.Id)
- agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return coreutils.DoneResponse(), err
}
if device.OperStatus != voltha.OperStatus_ACTIVE || device.ConnectStatus != voltha.ConnectStatus_REACHABLE || device.AdminState != voltha.AdminState_ENABLED {
- desc = "invalid device states"
- agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "invalid device states")
+ err = status.Errorf(codes.FailedPrecondition, "invalid device states")
+ return coreutils.DoneResponse(), err
}
dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
if err != nil {
- desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
- agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
-
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
+ return coreutils.DoneResponse(), err
}
flowsToAdd := make([]*ofp.OfpFlowStats, 0, len(updatedFlows))
@@ -273,10 +326,8 @@
if flowHandle, have := agent.flowCache.Lock(flow.Id); have {
flowToDelete := flowHandle.GetReadOnly()
// Update the store and cache
- if err := flowHandle.Update(ctx, flow); err != nil {
+ if err = flowHandle.Update(ctx, flow); err != nil {
flowHandle.Unlock()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
return coreutils.DoneResponse(), err
}
@@ -286,21 +337,17 @@
}
}
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
response := coreutils.NewResponse()
+ subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
// Process bulk flow update differently than incremental update
if !dType.AcceptsAddRemoveFlowUpdates {
updatedAllFlows := agent.listDeviceFlows()
- rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, nil)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
+ ctr, flowSlice := 0, make([]*ofp.OfpFlowStats, len(updatedAllFlows))
+ for _, flow := range updatedAllFlows {
+ flowSlice[ctr] = flow
+ ctr++
}
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateFlowToAdapter", rpcResponse, response)
+ go agent.sendBulkFlows(subCtx, device, &voltha.Flows{Items: flowSlice}, nil, flowMetadata, response)
} else {
logger.Debugw(ctx, "updating-flows-and-groups",
log.Fields{
@@ -311,7 +358,7 @@
// Sanity check
if (len(flowsToAdd) | len(flowsToDelete)) == 0 {
logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
- cancel()
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
@@ -324,18 +371,9 @@
ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
}
- rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
- }
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateFlowToAdapter", rpcResponse, response)
+ go agent.sendIncrementalFlows(subCtx, device, flowChanges, groupChanges, flowMetadata, response)
}
-
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
return response, nil
}
@@ -362,7 +400,7 @@
if err != nil {
return err
}
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, response); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.rpcTimeout, response); res != nil {
return status.Errorf(codes.Aborted, "errors-%s", res)
}
return nil
@@ -372,30 +410,29 @@
func (agent *Agent) deleteAllFlows(ctx context.Context) error {
logger.Debugw(ctx, "deleteAllFlows", log.Fields{"device-id": agent.deviceID})
- var error string
+ var err error
+ var errFlows string
var desc string
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
-
- defer agent.logDeviceUpdate(ctx, "deleteAllFlows", nil, nil, operStatus, &desc)
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
for flowID := range agent.flowCache.ListIDs() {
if flowHandle, have := agent.flowCache.Lock(flowID); have {
// Update the store and cache
- if err := flowHandle.Delete(ctx); err != nil {
+ if err = flowHandle.Delete(ctx); err != nil {
flowHandle.Unlock()
- error += fmt.Sprintf("%v ", flowID)
- logger.Errorw(ctx, "unable-to-delete-flow", log.Fields{"device-id": agent.deviceID, "flowID": flowID})
+ errFlows += fmt.Sprintf("%v ", flowID)
+ logger.Errorw(ctx, "unable-to-delete-flow", log.Fields{"device-id": agent.deviceID, "flowID": flowID, "error": err})
continue
}
flowHandle.Unlock()
}
}
- if error != "" {
- desc = fmt.Sprintf("Unable to delete flows : %s", error)
+ if errFlows != "" {
+ err = fmt.Errorf("unable to delete flows : %s", errFlows)
} else {
operStatus.Code = common.OperationResp_OPERATION_SUCCESS
}
-
- return nil
+ return err
}
diff --git a/rw_core/core/device/agent_group.go b/rw_core/core/device/agent_group.go
index ba58d2f..43a8929 100644
--- a/rw_core/core/device/agent_group.go
+++ b/rw_core/core/device/agent_group.go
@@ -18,15 +18,13 @@
import (
"context"
- "fmt"
- "strconv"
"github.com/gogo/protobuf/proto"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/common"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -47,32 +45,30 @@
func (agent *Agent) addGroupsToAdapter(ctx context.Context, newGroups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
logger.Debugw(ctx, "add-groups-to-adapters", log.Fields{"device-id": agent.deviceID, "groups": newGroups, "flow-metadata": flowMetadata})
+ var err error
var desc string
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
if (len(newGroups)) == 0 {
- logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "groups": newGroups})
+ desc = "no new groups"
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+ return coreutils.DoneResponse(), err
}
if !agent.proceedWithRequest(device) {
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", device.Id)
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return coreutils.DoneResponse(), err
}
dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
if err != nil {
- desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
+ return coreutils.DoneResponse(), err
}
groupsToAdd := make([]*ofp.OfpGroupEntry, 0)
@@ -80,8 +76,6 @@
for _, group := range newGroups {
groupHandle, created, err := agent.groupCache.LockOrCreate(ctx, group)
if err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
return coreutils.DoneResponse(), err
}
@@ -91,11 +85,9 @@
groupToChange := groupHandle.GetReadOnly()
if !proto.Equal(groupToChange, group) {
//Group needs to be updated.
- if err := groupHandle.Update(ctx, group); err != nil {
+ if err = groupHandle.Update(ctx, group); err != nil {
groupHandle.Unlock()
- desc = fmt.Sprintf("failure-updating-group-%s-to-device-%s", strconv.Itoa(int(group.Desc.GroupId)), agent.deviceID)
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.Internal, "failure-updating-group-%s-to-device-%s", strconv.Itoa(int(group.Desc.GroupId)), agent.deviceID)
+ return coreutils.DoneResponse(), err
}
groupsToDelete = append(groupsToDelete, groupToChange)
groupsToAdd = append(groupsToAdd, group)
@@ -109,25 +101,22 @@
}
// Sanity check
if (len(groupsToAdd)) == 0 {
- logger.Debugw(ctx, "no-groups-to-update", log.Fields{"device-id": agent.deviceID, "groups": newGroups})
+ desc = "no group to update"
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
// Send update to adapters
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
response := coreutils.NewResponse()
+ subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
if !dType.AcceptsAddRemoveFlowUpdates {
updatedAllGroups := agent.listDeviceGroups()
- rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, nil, updatedAllGroups, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
+ ctr, groupSlice := 0, make([]*ofp.OfpGroupEntry, len(updatedAllGroups))
+ for _, group := range updatedAllGroups {
+ groupSlice[ctr] = group
+ ctr++
}
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "addGroupsToAdapter", rpcResponse, response)
+ go agent.sendBulkFlows(subCtx, device, nil, &voltha.FlowGroups{Items: groupSlice}, flowMetadata, response)
} else {
flowChanges := &ofp.FlowChanges{
ToAdd: &voltha.Flows{Items: []*ofp.OfpFlowStats{}},
@@ -138,57 +127,46 @@
ToRemove: &voltha.FlowGroups{Items: groupsToDelete},
ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
}
- rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
- }
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "addGroupsToAdapter", rpcResponse, response)
+ go agent.sendIncrementalFlows(subCtx, device, flowChanges, groupChanges, flowMetadata, response)
}
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- agent.logDeviceUpdate(ctx, "addGroupsToAdapter", nil, nil, operStatus, &desc)
return response, nil
}
func (agent *Agent) deleteGroupsFromAdapter(ctx context.Context, groupsToDel []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
logger.Debugw(ctx, "delete-groups-from-adapter", log.Fields{"device-id": agent.deviceID, "groups": groupsToDel})
+ var desc string
+ var err error
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
if (len(groupsToDel)) == 0 {
- logger.Debugw(ctx, "nothing-to-delete", log.Fields{"device-id": agent.deviceID})
+ desc = "nothing to delete"
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
- var desc string
- operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
-
- defer agent.logDeviceUpdate(ctx, "deleteGroupsFromAdapter", nil, nil, operStatus, &desc)
-
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- desc = err.Error()
- return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+ return coreutils.DoneResponse(), err
}
if !agent.proceedWithRequest(device) {
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", device.Id)
- agent.logDeviceUpdate(ctx, "deleteGroupsFromAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return coreutils.DoneResponse(), err
}
dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
if err != nil {
- desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
+ return coreutils.DoneResponse(), err
}
for _, group := range groupsToDel {
if groupHandle, have := agent.groupCache.Lock(group.Desc.GroupId); have {
// Update the store and cache
- if err := groupHandle.Delete(ctx); err != nil {
+ if err = groupHandle.Delete(ctx); err != nil {
groupHandle.Unlock()
- desc = err.Error()
return coreutils.DoneResponse(), err
}
groupHandle.Unlock()
@@ -196,19 +174,16 @@
}
// Send update to adapters
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
response := coreutils.NewResponse()
+ subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
if !dType.AcceptsAddRemoveFlowUpdates {
updatedAllGroups := agent.listDeviceGroups()
- rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, nil, updatedAllGroups, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- return coreutils.DoneResponse(), err
+ ctr, groupSlice := 0, make([]*ofp.OfpGroupEntry, len(updatedAllGroups))
+ for _, group := range updatedAllGroups {
+ groupSlice[ctr] = group
+ ctr++
}
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteGroupsFromAdapter", rpcResponse, response)
+ go agent.sendBulkFlows(subCtx, device, nil, &voltha.FlowGroups{Items: groupSlice}, flowMetadata, response)
} else {
flowChanges := &ofp.FlowChanges{
ToAdd: &voltha.Flows{Items: []*ofp.OfpFlowStats{}},
@@ -219,13 +194,7 @@
ToRemove: &voltha.FlowGroups{Items: groupsToDel},
ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
}
- rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- return coreutils.DoneResponse(), err
- }
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteGroupsFromAdapter", rpcResponse, response)
+ go agent.sendIncrementalFlows(subCtx, device, flowChanges, groupChanges, flowMetadata, response)
}
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
return response, nil
@@ -235,47 +204,43 @@
logger.Debugw(ctx, "update-groups-to-adapter", log.Fields{"device-id": agent.deviceID, "groups": updatedGroups})
var desc string
+ var err error
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
if (len(updatedGroups)) == 0 {
- logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "groups": updatedGroups})
+ desc = "no groups to update"
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
+ return coreutils.DoneResponse(), err
}
if !agent.proceedWithRequest(device) {
- desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or Reconciling is in progress/failed", device.Id)
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return coreutils.DoneResponse(), err
}
if device.OperStatus != voltha.OperStatus_ACTIVE || device.ConnectStatus != voltha.ConnectStatus_REACHABLE || device.AdminState != voltha.AdminState_ENABLED {
- desc = fmt.Sprintf("invalid device states-oper-%s-connect-%s-admin-%s", device.OperStatus, device.ConnectStatus, device.AdminState)
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "invalid device states-oper-%s-connect-%s-admin-%s", device.OperStatus, device.ConnectStatus, device.AdminState)
+ err = status.Errorf(codes.FailedPrecondition, "invalid device states-oper-%s-connect-%s-admin-%s", device.OperStatus, device.ConnectStatus, device.AdminState)
+ return coreutils.DoneResponse(), err
}
dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
if err != nil {
- desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
+ err = status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
+ return coreutils.DoneResponse(), err
}
groupsToUpdate := make([]*ofp.OfpGroupEntry, 0)
for _, group := range updatedGroups {
if groupHandle, have := agent.groupCache.Lock(group.Desc.GroupId); have {
// Update the store and cache
- if err := groupHandle.Update(ctx, group); err != nil {
+ if err = groupHandle.Update(ctx, group); err != nil {
groupHandle.Unlock()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
return coreutils.DoneResponse(), err
}
groupsToUpdate = append(groupsToUpdate, group)
@@ -283,21 +248,17 @@
}
}
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
response := coreutils.NewResponse()
+ subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
// Process bulk flow update differently than incremental update
if !dType.AcceptsAddRemoveFlowUpdates {
updatedAllGroups := agent.listDeviceGroups()
- rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, nil, updatedAllGroups, nil)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
+ ctr, groupSlice := 0, make([]*ofp.OfpGroupEntry, len(updatedAllGroups))
+ for _, group := range updatedAllGroups {
+ groupSlice[ctr] = group
+ ctr++
}
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateGroupsToAdapter", rpcResponse, response)
+ go agent.sendBulkFlows(subCtx, device, nil, &voltha.FlowGroups{Items: groupSlice}, flowMetadata, response)
} else {
logger.Debugw(ctx, "updating-groups",
log.Fields{
@@ -307,8 +268,8 @@
// Sanity check
if (len(groupsToUpdate)) == 0 {
- logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "groups": groupsToUpdate})
- cancel()
+ desc = "nothing to update"
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return coreutils.DoneResponse(), nil
}
@@ -321,17 +282,9 @@
ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
ToUpdate: &voltha.FlowGroups{Items: groupsToUpdate},
}
- rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
- if err != nil {
- cancel()
- desc = err.Error()
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
- return coreutils.DoneResponse(), err
- }
- go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateGroupsToAdapter", rpcResponse, response)
+ go agent.sendIncrementalFlows(subCtx, device, flowChanges, groupChanges, flowMetadata, response)
}
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- agent.logDeviceUpdate(ctx, "updateGroupsToAdapter", nil, nil, operStatus, &desc)
return response, nil
}
diff --git a/rw_core/core/device/agent_image.go b/rw_core/core/device/agent_image.go
index e71af8a..0fda20e 100644
--- a/rw_core/core/device/agent_image.go
+++ b/rw_core/core/device/agent_image.go
@@ -18,20 +18,28 @@
import (
"context"
+ "errors"
+ "time"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-protos/v4/go/common"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+
+ "github.com/opencord/voltha-protos/v5/go/common"
"github.com/gogo/protobuf/proto"
- "github.com/golang/protobuf/ptypes"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func (agent *Agent) downloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ var err error
+ var desc string
+ var prevAdminState, currAdminState common.AdminState_Types
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, &prevAdminState, &currAdminState, operStatus, err, desc) }()
+
if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
@@ -39,23 +47,26 @@
if agent.device.Root {
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, is an OLT. Image update "+
+ err = status.Errorf(codes.FailedPrecondition, "device-id:%s, is an OLT. Image update "+
"not supported by VOLTHA. Use Device Manager or other means", agent.deviceID)
+ return nil, err
}
device := agent.cloneDeviceWithoutLock()
if !agent.proceedWithRequest(device) {
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed.",
- agent.deviceID)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return nil, err
}
if device.ImageDownloads != nil {
for _, image := range device.ImageDownloads {
if image.DownloadState == voltha.ImageDownload_DOWNLOAD_REQUESTED {
- return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, already downloading image:%s",
+ err = status.Errorf(codes.FailedPrecondition, "device-id:%s, already downloading image:%s",
agent.deviceID, image.Name)
+ agent.requestQueue.RequestComplete()
+ return nil, err
}
}
}
@@ -71,22 +82,39 @@
cloned.ImageDownloads[index] = clonedImg
}
- cloned.AdminState = voltha.AdminState_DOWNLOADING_IMAGE
- if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
- return nil, err
- }
-
// Send the request to the adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.DownloadImage(subCtx, cloned, clonedImg)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- cancel()
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
- go agent.waitForAdapterResponse(subCtx, cancel, "downloadImage", ch, agent.onImageSuccess, agent.onImageFailure)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+ operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ response, err := client.DownloadImage(subCtx, &ic.ImageDownloadMessage{
+ Device: cloned,
+ Image: clonedImg,
+ })
+ if err == nil {
+ agent.onImageSuccess(subCtx, response)
+ } else {
+ agent.onImageFailure(subCtx, err)
+ }
+ }()
+ cloned.AdminState = voltha.AdminState_DOWNLOADING_IMAGE
+ if err = agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
+ return nil, err
+ }
return &common.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
}
@@ -102,7 +130,14 @@
}
func (agent *Agent) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+
+ var err error
+ var desc string
+ var prevAdminState, currAdminState common.AdminState_Types
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, &prevAdminState, &currAdminState, operStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": agent.deviceID})
@@ -111,8 +146,8 @@
if !agent.proceedWithRequest(cloned) {
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed.",
- agent.deviceID)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return nil, err
}
// Update image download state
@@ -121,33 +156,59 @@
agent.requestQueue.RequestComplete()
return nil, err
}
-
+ prevAdminState = cloned.AdminState
cloned.ImageDownloads[index].DownloadState = voltha.ImageDownload_DOWNLOAD_CANCELLED
if cloned.AdminState != voltha.AdminState_DOWNLOADING_IMAGE {
+ err = status.Errorf(codes.Aborted, "device not in image download state %s", cloned.Id)
agent.requestQueue.RequestComplete()
- } else {
- // Set the device to Enabled
- cloned.AdminState = voltha.AdminState_ENABLED
- if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
- return nil, err
- }
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.CancelImageDownload(subCtx, cloned, img)
- if err != nil {
- cancel()
- return nil, err
- }
- go agent.waitForAdapterResponse(subCtx, cancel, "cancelImageDownload", ch, agent.onImageSuccess,
- agent.onImageFailure)
+ return &voltha.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}, err
}
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
+ return nil, err
+ }
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+ operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ response, err := client.CancelImageDownload(subCtx, &ic.ImageDownloadMessage{
+ Device: cloned,
+ Image: img,
+ })
+ if err == nil {
+ agent.onImageSuccess(subCtx, response)
+ } else {
+ agent.onImageFailure(subCtx, err)
+ }
+ }()
+
+ // Set the device to Enabled
+ cloned.AdminState = voltha.AdminState_ENABLED
+ if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
+ return nil, err
+ }
+ currAdminState = cloned.AdminState
+
return &voltha.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
}
func (agent *Agent) activateImage(ctx context.Context, img *voltha.ImageDownload) (*voltha.OperationResp, error) {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
logger.Debugw(ctx, "activate-image", log.Fields{"device-id": agent.deviceID})
@@ -155,9 +216,9 @@
cloned := agent.cloneDeviceWithoutLock()
if !agent.proceedWithRequest(cloned) {
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, Cannot complete operation as device deletion is in progress or reconcile is in progress/failed.",
- agent.deviceID)
+ return nil, err
}
// Update image download state
@@ -169,72 +230,125 @@
if image.DownloadState != voltha.ImageDownload_DOWNLOAD_SUCCEEDED {
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, device-has-not-downloaded-image:%s", agent.deviceID, img.Name)
+ err = status.Errorf(codes.FailedPrecondition, "device-id:%s, device-has-not-downloaded-image:%s", agent.deviceID, img.Name)
+ return nil, err
}
//TODO does this need to be removed ?
if cloned.AdminState == voltha.AdminState_DOWNLOADING_IMAGE {
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, device-in-downloading-state:%s", agent.deviceID, img.Name)
+ err = status.Errorf(codes.FailedPrecondition, "device-id:%s, device-in-downloading-state:%s", agent.deviceID, img.Name)
+ return nil, err
}
- // Save the image
+ // Update the image
cloned.ImageDownloads[index].ImageState = voltha.ImageDownload_IMAGE_ACTIVATING
-
cloned.AdminState = voltha.AdminState_DOWNLOADING_IMAGE
+
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ return nil, err
+ }
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+ operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ response, err := client.ActivateImageUpdate(subCtx, &ic.ImageDownloadMessage{
+ Device: cloned,
+ Image: img,
+ })
+ if err == nil {
+ agent.onImageSuccess(subCtx, response)
+ } else {
+ agent.onImageFailure(subCtx, err)
+ }
+ }()
+
+ // Save the image
if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
return nil, err
}
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.ActivateImageUpdate(subCtx, cloned, img)
- if err != nil {
- cancel()
- return nil, err
- }
- go agent.waitForAdapterResponse(subCtx, cancel, "activateImageUpdate", ch, agent.onImageSuccess, agent.onFailure)
-
// The status of the AdminState will be changed following the update_download_status response from the adapter
// The image name will also be removed from the device list
return &voltha.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
}
func (agent *Agent) revertImage(ctx context.Context, img *voltha.ImageDownload) (*voltha.OperationResp, error) {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
logger.Debugw(ctx, "revert-image", log.Fields{"device-id": agent.deviceID})
- // Update image download state
cloned := agent.cloneDeviceWithoutLock()
+ if !agent.proceedWithRequest(cloned) {
+ agent.requestQueue.RequestComplete()
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return nil, err
+ }
+
+ // Update image download state
_, index, err := getImage(img, cloned)
if err != nil {
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, image-not-registered:%s", agent.deviceID, img.Name)
+ err = status.Errorf(codes.FailedPrecondition, "deviceId:%s, image-not-registered:%s", agent.deviceID, img.Name)
+ return nil, err
}
if cloned.AdminState != voltha.AdminState_ENABLED {
agent.requestQueue.RequestComplete()
- return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, device-not-enabled-state:%s", agent.deviceID, img.Name)
+ err = status.Errorf(codes.FailedPrecondition, "deviceId:%s, device-not-enabled-state:%s", agent.deviceID, img.Name)
+ return nil, err
}
cloned.ImageDownloads[index].ImageState = voltha.ImageDownload_IMAGE_REVERTING
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
+ return nil, err
+ }
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+ operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
+ go func() {
+ defer cancel()
+ _, err := client.RevertImageUpdate(subCtx, &ic.ImageDownloadMessage{
+ Device: cloned,
+ Image: img,
+ })
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
+ }
+ }()
+ // Save data
if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
return nil, err
}
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, err := agent.adapterProxy.RevertImageUpdate(subCtx, cloned, img)
- if err != nil {
- cancel()
- return nil, err
- }
- go agent.waitForAdapterResponse(subCtx, cancel, "revertImageUpdate", ch, agent.onSuccess, agent.onFailure)
-
return &voltha.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
}
@@ -244,40 +358,49 @@
if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return nil, err
}
+ defer agent.requestQueue.RequestComplete()
+
device := agent.getDeviceReadOnlyWithoutLock()
- ch, err := agent.adapterProxy.GetImageDownloadStatus(ctx, device, img)
- agent.requestQueue.RequestComplete()
+ if !agent.proceedWithRequest(device) {
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ }
+
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
return nil, err
}
- // Wait for the adapter response
- rpcResponse, ok := <-ch
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
- }
- if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
- }
- // Successful response
- imgDownload := &voltha.ImageDownload{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, imgDownload); err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "%s", err.Error())
- }
- return imgDownload, nil
+ return client.GetImageDownloadStatus(ctx, &ic.ImageDownloadMessage{
+ Device: device,
+ Image: img,
+ })
}
func (agent *Agent) updateImageDownload(ctx context.Context, img *voltha.ImageDownload) error {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ var err error
+ var desc string
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return err
}
+
logger.Debugw(ctx, "updating-image-download", log.Fields{"device-id": agent.deviceID, "img": img})
cloned := agent.cloneDeviceWithoutLock()
if !agent.proceedWithRequest(cloned) {
agent.requestQueue.RequestComplete()
- return status.Errorf(codes.FailedPrecondition, "deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed.",
- agent.deviceID)
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ return err
}
// Update the image as well as remove it if the download was cancelled
@@ -326,14 +449,25 @@
}
// onImageFailure brings back the device to Enabled state and sets the image to image download_failed.
-func (agent *Agent) onImageFailure(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
+func (agent *Agent) onImageFailure(ctx context.Context, imgErr error) {
// original context has failed due to timeout , let's open a new one
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.internalTimeout)
subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
defer cancel()
+ rpc := coreutils.GetRPCMetadataFromContext(subCtx)
+
+ defer func() {
+ eCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
+ rpce := agent.deviceMgr.NewRPCEvent(eCtx, agent.deviceID, imgErr.Error(), nil)
+ go agent.deviceMgr.SendRPCEvent(eCtx, "RPC_ERROR_RAISE_EVENT", rpce,
+ voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ desc := "adapter-response"
+ agent.logDeviceUpdate(ctx, nil, nil, operStatus, imgErr, desc)
+ }()
if err := agent.requestQueue.WaitForGreenLight(subCtx); err != nil {
- logger.Errorw(subCtx, "can't obtain lock", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": err, "args": reqArgs})
+ logger.Errorw(subCtx, "can't obtain lock", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": err})
return
}
@@ -345,8 +479,8 @@
log.Fields{"rpc": rpc, "device-id": agent.deviceID})
return
}
- if res, ok := response.(error); ok {
- logger.Errorw(subCtx, "rpc-failed", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": res, "args": reqArgs})
+ if imgErr != nil {
+ logger.Errorw(subCtx, "rpc-failed", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": imgErr})
cloned := agent.cloneDeviceWithoutLock()
//TODO base this on IMAGE ID when created
var imageFailed *voltha.ImageDownload
@@ -362,7 +496,7 @@
}
if imageFailed == nil {
- logger.Errorw(subCtx, "can't find image", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
+ logger.Errorw(subCtx, "can't find image", log.Fields{"rpc": rpc, "device-id": agent.deviceID})
return
}
@@ -376,19 +510,24 @@
cloned.AdminState = voltha.AdminState_ENABLED
if err := agent.updateDeviceAndReleaseLock(subCtx, cloned); err != nil {
logger.Errorw(subCtx, "failed-enable-device-after-image-failure",
- log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": res, "args": reqArgs})
+ log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": err})
}
} else {
- logger.Errorw(subCtx, "rpc-failed-invalid-error", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
+ logger.Errorw(subCtx, "rpc-failed-invalid-error", log.Fields{"rpc": rpc, "device-id": agent.deviceID})
return
}
- // TODO: Post failure message onto kafka
}
// onImageSuccess brings back the device to Enabled state and sets the image to image download_failed.
-func (agent *Agent) onImageSuccess(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- logger.Errorw(ctx, "cannot-obtain-lock", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": err, "args": reqArgs})
+func (agent *Agent) onImageSuccess(ctx context.Context, response interface{}) {
+ rpc := coreutils.GetRPCMetadataFromContext(ctx)
+
+ var err error
+ var desc string
+ operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
+
+ if err = agent.requestQueue.WaitForGreenLight(ctx); err != nil {
return
}
@@ -396,12 +535,10 @@
if !agent.proceedWithRequest(cloned) {
agent.requestQueue.RequestComplete()
- logger.Errorw(ctx, "Cannot complete operation as Device deletion is in progress or reconciling is in progress/failed.",
- log.Fields{"rpc": rpc, "device-id": agent.deviceID})
+ err = status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
return
}
- logger.Infow(ctx, "rpc-successful", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "response": response, "args": reqArgs})
-
+ logger.Infow(ctx, "rpc-successful", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "response": response})
//TODO base this on IMAGE ID when created
var imageSucceeded *voltha.ImageDownload
var index int
@@ -416,7 +553,7 @@
}
if imageSucceeded == nil {
- logger.Errorw(ctx, "can't find image", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
+ err = errors.New("can't find image")
return
}
//update image state on success
@@ -427,11 +564,14 @@
}
//Enabled is the only state we can go back to.
cloned.AdminState = voltha.AdminState_ENABLED
- if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
+ if err = agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
logger.Errorw(ctx, "failed-enable-device-after-image-download-success",
- log.Fields{"rpc": rpc, "device-id": agent.deviceID, "response": response, "args": reqArgs})
+ log.Fields{"rpc": rpc, "device-id": agent.deviceID, "response": response})
}
-
+ // Update operation status
+ if err == nil {
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
+ }
}
func (agent *Agent) downloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
@@ -447,19 +587,30 @@
}
cloned := agent.cloneDeviceWithoutLock()
+ if !agent.proceedWithRequest(cloned) {
+ agent.requestQueue.RequestComplete()
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ }
// Send the request to the adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
+ return nil, err
+ }
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
defer cancel()
subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
- ch, err := agent.adapterProxy.DownloadImageToOnuDevice(subCtx, cloned, request)
agent.requestQueue.RequestComplete()
- if err != nil {
- return nil, err
- }
-
- return agent.getDeviceImageResponseFromAdapter(ctx, ch)
+ return client.DownloadOnuImage(subCtx, request)
}
func (agent *Agent) getImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
@@ -467,21 +618,33 @@
return nil, err
}
- cloned := agent.cloneDeviceWithoutLock()
-
- // Send the request to the adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- defer cancel()
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
logger.Debugw(ctx, "get-image-status", log.Fields{"device-id": agent.deviceID})
- ch, err := agent.adapterProxy.GetOnuImageStatus(subCtx, cloned, request)
- agent.requestQueue.RequestComplete()
+ cloned := agent.cloneDeviceWithoutLock()
+ if !agent.proceedWithRequest(cloned) {
+ agent.requestQueue.RequestComplete()
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ }
+
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
- return agent.getDeviceImageResponseFromAdapter(subCtx, ch)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ defer cancel()
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+
+ return client.GetOnuImageStatus(subCtx, request)
}
func (agent *Agent) activateImageOnDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
@@ -489,21 +652,35 @@
return nil, err
}
- cloned := agent.cloneDeviceWithoutLock()
-
- // Send the request to the adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- defer cancel()
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
logger.Debugw(ctx, "activate-image-on-device", log.Fields{"device-id": agent.deviceID})
- ch, err := agent.adapterProxy.ActivateOnuImage(subCtx, cloned, request)
- agent.requestQueue.RequestComplete()
+ cloned := agent.cloneDeviceWithoutLock()
+
+ if !agent.proceedWithRequest(cloned) {
+ agent.requestQueue.RequestComplete()
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ }
+
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
- return agent.getDeviceImageResponseFromAdapter(subCtx, ch)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ defer cancel()
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+
+ agent.requestQueue.RequestComplete()
+ return client.ActivateOnuImage(subCtx, request)
}
func (agent *Agent) abortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
@@ -511,21 +688,35 @@
return nil, err
}
- cloned := agent.cloneDeviceWithoutLock()
-
- // Send the request to the adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- defer cancel()
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
logger.Debugw(ctx, "abort-image-on-device", log.Fields{"device-id": agent.deviceID})
- ch, err := agent.adapterProxy.AbortImageUpgrade(subCtx, cloned, request)
- agent.requestQueue.RequestComplete()
- if err != nil {
- return nil, err
+ cloned := agent.cloneDeviceWithoutLock()
+
+ if !agent.proceedWithRequest(cloned) {
+ agent.requestQueue.RequestComplete()
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
}
- return agent.getDeviceImageResponseFromAdapter(ctx, ch)
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
+ return nil, err
+ }
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ defer cancel()
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+
+ agent.requestQueue.RequestComplete()
+
+ return client.AbortOnuImageUpgrade(subCtx, request)
}
func (agent *Agent) commitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
@@ -533,21 +724,33 @@
return nil, err
}
- cloned := agent.cloneDeviceWithoutLock()
-
- // Send the request to the adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- defer cancel()
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
logger.Debugw(ctx, "commit-image-on-device", log.Fields{"device-id": agent.deviceID})
- ch, err := agent.adapterProxy.CommitImage(subCtx, cloned, request)
- agent.requestQueue.RequestComplete()
- if err != nil {
- return nil, err
+ cloned := agent.cloneDeviceWithoutLock()
+
+ if !agent.proceedWithRequest(cloned) {
+ agent.requestQueue.RequestComplete()
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
}
- return agent.getDeviceImageResponseFromAdapter(ctx, ch)
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
+ return nil, err
+ }
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.rpcTimeout)
+ defer cancel()
+ subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
+
+ return client.CommitOnuImage(subCtx, request)
}
func (agent *Agent) getOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
@@ -555,63 +758,29 @@
return nil, err
}
- cloned := agent.cloneDeviceWithoutLock()
-
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- defer cancel()
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
logger.Debug(ctx, "get-onu-images")
+ cloned := agent.cloneDeviceWithoutLock()
+
+ if !agent.proceedWithRequest(cloned) {
+ agent.requestQueue.RequestComplete()
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", "cannot complete operation as device deletion is in progress or reconciling is in progress/failed")
+ }
+
// Send the request to the adapter
- ch, err := agent.adapterProxy.GetOnuImages(subCtx, cloned, id)
- agent.requestQueue.RequestComplete()
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": cloned.AdapterEndpoint,
+ })
+ agent.requestQueue.RequestComplete()
return nil, err
}
- //wait for adapter response
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
- } else if rpcResponse.Err != nil {
- // return error
- return nil, status.Errorf(codes.Internal, "%s", rpcResponse.Err.Error())
- } else {
- resp := &voltha.OnuImages{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, resp); err != nil {
- return nil, status.Errorf(codes.Internal, "%s", err.Error())
- }
-
- return resp, nil
- }
- case <-ctx.Done():
- return nil, ctx.Err()
- }
-}
-
-func (agent *Agent) getDeviceImageResponseFromAdapter(ctx context.Context, ch chan *kafka.RpcResponse) (*voltha.DeviceImageResponse, error) {
- //wait for adapter response
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
- } else if rpcResponse.Err != nil {
- // return error
- return nil, status.Errorf(codes.Internal, "%s", rpcResponse.Err.Error())
- } else {
- resp := &voltha.DeviceImageResponse{}
- if err := ptypes.UnmarshalAny(rpcResponse.Reply, resp); err != nil {
- return nil, status.Errorf(codes.Internal, "%s", err.Error())
- }
-
- if len(resp.DeviceImageStates) == 0 || resp.DeviceImageStates[0] == nil {
- return nil, status.Errorf(codes.Internal, "invalid response from adapter")
- }
-
- return resp, nil
- }
- case <-ctx.Done():
- return nil, ctx.Err()
- }
+ agent.requestQueue.RequestComplete()
+ return client.GetOnuImages(ctx, id)
}
diff --git a/rw_core/core/device/agent_pm_config.go b/rw_core/core/device/agent_pm_config.go
index 176a126..ba1005a 100644
--- a/rw_core/core/device/agent_pm_config.go
+++ b/rw_core/core/device/agent_pm_config.go
@@ -18,79 +18,73 @@
import (
"context"
- "fmt"
+ "time"
+
"github.com/gogo/protobuf/proto"
- coreutils "github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
- "time"
)
func (agent *Agent) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
logger.Debugw(ctx, "update-pm-configs", log.Fields{"device-id": pmConfigs.Id})
- cloned := agent.cloneDeviceWithoutLock()
+ var rpce *voltha.RPCEvent
+ defer func() {
+ if rpce != nil {
+ go agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
+ voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
+ }
+ }()
+
+ cloned, err := agent.getDeviceReadOnly(ctx)
+ if err != nil {
+ return err
+ }
if !agent.proceedWithRequest(cloned) {
return status.Errorf(codes.FailedPrecondition, "deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", cloned.Id)
}
- cloned.PmConfigs = proto.Clone(pmConfigs).(*voltha.PmConfigs)
+ // We need to send the response for the PM Config Updates in a synchronous manner to the adapter.
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
+ if err != nil {
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": agent.adapterEndpoint,
+ })
+ return err
+ }
+ _, pmErr := client.UpdatePmConfig(ctx, &ic.PmConfigsInfo{
+ DeviceId: agent.deviceID,
+ PmConfigs: pmConfigs,
+ })
- // Send the request to the adapter
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- defer cancel()
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
-
- ch, pmErr := agent.adapterProxy.UpdatePmConfigs(subCtx, cloned, pmConfigs)
if pmErr != nil {
+ rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, pmErr.Error(), nil)
return pmErr
}
-
- var rpce *voltha.RPCEvent
- defer func() {
- if rpce != nil {
- agent.deviceMgr.SendRPCEvent(ctx, "RPC_ERROR_RAISE_EVENT", rpce,
- voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
- }
- }()
- // We need to send the response for the PM Config Updates in a synchronous manner to the caller.
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- pmErr = fmt.Errorf("response-channel-closed")
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, pmErr.Error(), nil)
- } else if rpcResponse.Err != nil {
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, rpcResponse.Err.Error(), nil)
- pmErr = rpcResponse.Err
- }
- case <-ctx.Done():
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, ctx.Err().Error(), nil)
- pmErr = ctx.Err()
- }
-
// In case of no error for PM Config update, commit the new PM Config to DB.
- if pmErr == nil {
- // acquire lock for update the device to DB
- if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
- return err
- }
- // the Device properties might have changed due to other concurrent transactions on the device, so get latest copy
- cloned = agent.cloneDeviceWithoutLock()
- // commit new pm config
- cloned.PmConfigs = proto.Clone(pmConfigs).(*voltha.PmConfigs)
-
- // Store back the device to DB and release lock
- if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
- logger.Errorw(ctx, "error-updating-device-context-to-db", log.Fields{"device-id": agent.deviceID})
- rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, err.Error(), nil)
- return err
- }
+ if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ return err
}
+ // the Device properties might have changed due to other concurrent transactions on the device, so get latest copy
+ cloned = agent.cloneDeviceWithoutLock()
+ // commit new pm config
+ cloned.PmConfigs = proto.Clone(pmConfigs).(*voltha.PmConfigs)
- return pmErr
+ // Store back the device to DB and release lock
+ if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
+ logger.Errorw(ctx, "error-updating-device-context-to-db", log.Fields{"device-id": agent.deviceID})
+ rpce = agent.deviceMgr.NewRPCEvent(ctx, agent.deviceID, err.Error(), nil)
+ return err
+ }
+ return nil
}
func (agent *Agent) initPmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
diff --git a/rw_core/core/device/agent_port.go b/rw_core/core/device/agent_port.go
index f9bf7de..e7bb371 100644
--- a/rw_core/core/device/agent_port.go
+++ b/rw_core/core/device/agent_port.go
@@ -19,13 +19,14 @@
import (
"context"
"fmt"
- "github.com/opencord/voltha-protos/v4/go/common"
+
+ "github.com/opencord/voltha-protos/v5/go/common"
"github.com/gogo/protobuf/proto"
"github.com/opencord/voltha-go/rw_core/core/device/port"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -149,9 +150,10 @@
func (agent *Agent) addPort(ctx context.Context, port *voltha.Port) error {
logger.Debugw(ctx, "addPort", log.Fields{"device-id": agent.deviceID})
var desc string
+ var err error
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
- defer agent.logDeviceUpdate(ctx, "addPort", nil, nil, operStatus, &desc)
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
port.AdminState = voltha.AdminState_ENABLED
@@ -171,6 +173,7 @@
if oldPort.Label != "" || oldPort.Type != voltha.Port_PON_OLT {
logger.Debugw(ctx, "port-already-exists", log.Fields{"port": port})
desc = fmt.Sprintf("port already exists, port : %s", port)
+ operStatus.Code = common.OperationResp_OPERATION_SUCCESS
return nil
}
@@ -237,97 +240,118 @@
func (agent *Agent) disablePort(ctx context.Context, portID uint32) error {
logger.Debugw(ctx, "disable-port", log.Fields{"device-id": agent.deviceID, "port-no": portID})
+ var err error
var desc string
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
-
- defer agent.logDeviceUpdate(ctx, "disablePort", nil, nil, operStatus, &desc)
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
portHandle, have := agent.portLoader.Lock(portID)
if !have {
- desc = fmt.Sprintf("Invalid argument portID: %v", portID)
- return status.Errorf(codes.InvalidArgument, "%v", portID)
+ err = status.Errorf(codes.InvalidArgument, "%v", portID)
+ return err
}
defer portHandle.Unlock()
oldPort := portHandle.GetReadOnly()
if oldPort.Type != voltha.Port_PON_OLT {
- desc = fmt.Sprintf("Disabling of Port Type %v unimplemented", oldPort.Type)
- return status.Errorf(codes.InvalidArgument, "Disabling of Port Type %v unimplemented", oldPort.Type)
+ err = status.Errorf(codes.Unimplemented, "disabling of Port Type %v unimplemented", oldPort.Type)
+ return err
}
newPort := *oldPort
newPort.AdminState = voltha.AdminState_DISABLED
if err := portHandle.Update(ctx, &newPort); err != nil {
- desc = err.Error()
return err
}
//send request to adapter
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- desc = err.Error()
return err
}
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
- ch, err := agent.adapterProxy.DisablePort(ctx, device, &newPort)
+ // Send the request to the adapter
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- desc = err.Error()
- cancel()
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
return err
}
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "disablePort", ch, agent.onSuccess, agent.onFailure, nil)
+ go func() {
+ defer cancel()
+ _, err := client.DisablePort(subCtx, &newPort)
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
+ }
+ }()
return nil
}
func (agent *Agent) enablePort(ctx context.Context, portID uint32) error {
logger.Debugw(ctx, "enable-port", log.Fields{"device-id": agent.deviceID, "port-no": portID})
+ var err error
var desc string
operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
-
- defer agent.logDeviceUpdate(ctx, "enablePort", nil, nil, operStatus, &desc)
+ defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
portHandle, have := agent.portLoader.Lock(portID)
if !have {
- desc = fmt.Sprintf("Invalid Argument portID: %v", portID)
- return status.Errorf(codes.InvalidArgument, "%v", portID)
+ err = status.Errorf(codes.InvalidArgument, "%v", portID)
+ return err
}
defer portHandle.Unlock()
oldPort := portHandle.GetReadOnly()
if oldPort.Type != voltha.Port_PON_OLT {
- desc = fmt.Sprintf("Enabling of Port Type %v unimplemented", oldPort.Type)
- return status.Errorf(codes.InvalidArgument, "Enabling of Port Type %v unimplemented", oldPort.Type)
+ err = status.Errorf(codes.Unimplemented, "enabling of Port Type %v unimplemented", oldPort.Type)
+ return err
}
newPort := *oldPort
newPort.AdminState = voltha.AdminState_ENABLED
- if err := portHandle.Update(ctx, &newPort); err != nil {
- desc = err.Error()
+ if err = portHandle.Update(ctx, &newPort); err != nil {
return err
}
//send request to adapter
device, err := agent.getDeviceReadOnly(ctx)
if err != nil {
- desc = err.Error()
return err
}
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
- subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
- ch, err := agent.adapterProxy.EnablePort(ctx, device, &newPort)
+ client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
if err != nil {
- desc = err.Error()
- cancel()
+ logger.Errorw(ctx, "grpc-client-nil",
+ log.Fields{
+ "error": err,
+ "device-id": agent.deviceID,
+ "device-type": agent.deviceType,
+ "adapter-endpoint": device.AdapterEndpoint,
+ })
return err
}
+ subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
- go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "enablePort", ch, agent.onSuccess, agent.onFailure, nil)
+ go func() {
+ defer cancel()
+ _, err := client.EnablePort(subCtx, &newPort)
+ if err == nil {
+ agent.onSuccess(subCtx, nil, nil, true)
+ } else {
+ agent.onFailure(subCtx, err, nil, nil, true)
+ }
+ }()
return nil
}
diff --git a/rw_core/core/device/agent_test.go b/rw_core/core/device/agent_test.go
index e3716a7..0577c1e 100755
--- a/rw_core/core/device/agent_test.go
+++ b/rw_core/core/device/agent_test.go
@@ -18,7 +18,6 @@
import (
"context"
- "fmt"
"math/rand"
"sort"
"strconv"
@@ -27,21 +26,23 @@
"testing"
"time"
+ ver "github.com/opencord/voltha-lib-go/v7/pkg/version"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+
"github.com/gogo/protobuf/proto"
"github.com/opencord/voltha-go/db/model"
"github.com/opencord/voltha-go/rw_core/config"
"github.com/opencord/voltha-go/rw_core/core/adapter"
- cm "github.com/opencord/voltha-go/rw_core/mocks"
tst "github.com/opencord/voltha-go/rw_core/test"
- com "github.com/opencord/voltha-lib-go/v5/pkg/adapters/common"
- "github.com/opencord/voltha-lib-go/v5/pkg/db"
- "github.com/opencord/voltha-lib-go/v5/pkg/events"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- mock_etcd "github.com/opencord/voltha-lib-go/v5/pkg/mocks/etcd"
- mock_kafka "github.com/opencord/voltha-lib-go/v5/pkg/mocks/kafka"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ com "github.com/opencord/voltha-lib-go/v7/pkg/adapters/common"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db"
+ "github.com/opencord/voltha-lib-go/v7/pkg/events"
+ "github.com/opencord/voltha-lib-go/v7/pkg/kafka"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ mock_etcd "github.com/opencord/voltha-lib-go/v7/pkg/mocks/etcd"
+ mock_kafka "github.com/opencord/voltha-lib-go/v7/pkg/mocks/kafka"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"github.com/phayes/freeport"
"github.com/stretchr/testify/assert"
)
@@ -51,17 +52,13 @@
deviceMgr *Manager
logicalDeviceMgr *LogicalManager
adapterMgr *adapter.Manager
- kmp kafka.InterContainerProxy
kClient kafka.Client
kEventClient kafka.Client
kvClientPort int
- oltAdapter *cm.OLTAdapter
- onuAdapter *cm.ONUAdapter
oltAdapterName string
onuAdapterName string
coreInstanceID string
- defaultTimeout time.Duration
- maxTimeout time.Duration
+ internalTimeout time.Duration
device *voltha.Device
devicePorts map[uint32]*voltha.Port
done chan int
@@ -78,24 +75,22 @@
// Create the kafka client
test.kClient = mock_kafka.NewKafkaClient()
test.kEventClient = mock_kafka.NewKafkaClient()
- test.oltAdapterName = "olt_adapter_mock"
- test.onuAdapterName = "onu_adapter_mock"
+ test.oltAdapterName = "olt-mock-adapter"
+ test.onuAdapterName = "onu-mock-adapter"
test.coreInstanceID = "rw-da-test"
- test.defaultTimeout = 5 * time.Second
- test.maxTimeout = 20 * time.Second
+ test.internalTimeout = 5 * time.Second
test.done = make(chan int)
parentID := com.GetRandomString(10)
test.device = &voltha.Device{
- Type: "onu_adapter_mock",
+ Type: "onu-mock-device-type",
ParentId: parentID,
ParentPortNo: 1,
- VendorId: "onu_adapter_mock",
- Adapter: "onu_adapter_mock",
+ VendorId: "onu-mock-vendor",
Vlan: 100,
Address: nil,
ProxyAddress: &voltha.Device_ProxyAddress{
DeviceId: parentID,
- DeviceType: "olt_adapter_mock",
+ DeviceType: "olt-mock-device-type",
ChannelId: 100,
ChannelGroupId: 0,
ChannelTermination: "",
@@ -119,15 +114,14 @@
func (dat *DATest) startCore(ctx context.Context) {
cfg := &config.RWCoreFlags{}
cfg.ParseCommandArguments([]string{})
- cfg.CoreTopic = "rw_core"
cfg.EventTopic = "voltha.events"
- cfg.DefaultRequestTimeout = dat.defaultTimeout
+ cfg.InternalTimeout = dat.internalTimeout
cfg.KVStoreAddress = "127.0.0.1" + ":" + strconv.Itoa(dat.kvClientPort)
grpcPort, err := freeport.GetFreePort()
if err != nil {
logger.Fatal(ctx, "Cannot get a freeport for grpc")
}
- cfg.GrpcAddress = "127.0.0.1" + ":" + strconv.Itoa(grpcPort)
+ cfg.GrpcNBIAddress = "127.0.0.1" + ":" + strconv.Itoa(grpcPort)
client := tst.SetupKVClient(ctx, cfg, dat.coreInstanceID)
backend := &db.Backend{
Client: client,
@@ -135,34 +129,20 @@
Address: cfg.KVStoreAddress,
Timeout: cfg.KVStoreTimeout,
LivenessChannelInterval: cfg.LiveProbeInterval / 2}
- dat.kmp = kafka.NewInterContainerProxy(
- kafka.InterContainerAddress(cfg.KafkaAdapterAddress),
- kafka.MsgClient(dat.kClient),
- kafka.DefaultTopic(&kafka.Topic{Name: cfg.CoreTopic}))
- endpointMgr := kafka.NewEndpointManager(backend)
proxy := model.NewDBPath(backend)
- dat.adapterMgr = adapter.NewAdapterManager(ctx, proxy, dat.coreInstanceID, dat.kClient)
+ dat.adapterMgr = adapter.NewAdapterManager(proxy, dat.coreInstanceID, backend, 5)
eventProxy := events.NewEventProxy(events.MsgClient(dat.kEventClient), events.MsgTopic(kafka.Topic{Name: cfg.EventTopic}))
- dat.deviceMgr, dat.logicalDeviceMgr = NewManagers(proxy, dat.adapterMgr, dat.kmp, endpointMgr, cfg, dat.coreInstanceID, eventProxy)
- dat.adapterMgr.Start(context.Background())
- if err = dat.kmp.Start(ctx); err != nil {
- logger.Fatal(ctx, "Cannot start InterContainerProxy")
- }
-
- if err := dat.kmp.SubscribeWithDefaultRequestHandler(ctx, kafka.Topic{Name: cfg.CoreTopic}, kafka.OffsetNewest); err != nil {
- logger.Fatalf(ctx, "Cannot add default request handler: %s", err)
- }
-
+ dat.deviceMgr, dat.logicalDeviceMgr = NewManagers(proxy, dat.adapterMgr, cfg, dat.coreInstanceID, eventProxy)
+ dat.adapterMgr.Start(context.Background(), "agent-test")
+ dat.registerAdapters(context.Background())
+ log.SetAllLogLevel(log.FatalLevel)
}
func (dat *DATest) stopAll(ctx context.Context) {
if dat.kClient != nil {
dat.kClient.Stop(ctx)
}
- if dat.kmp != nil {
- dat.kmp.Stop(ctx)
- }
if dat.etcdServer != nil {
tst.StopEmbeddedEtcdServer(ctx, dat.etcdServer)
}
@@ -174,7 +154,7 @@
func (dat *DATest) createDeviceAgent(t *testing.T) *Agent {
deviceMgr := dat.deviceMgr
clonedDevice := proto.Clone(dat.device).(*voltha.Device)
- deviceAgent := newAgent(deviceMgr.adapterProxy, clonedDevice, deviceMgr, deviceMgr.dbPath, deviceMgr.dProxy, deviceMgr.defaultTimeout)
+ deviceAgent := newAgent(clonedDevice, deviceMgr, deviceMgr.dbPath, deviceMgr.dProxy, deviceMgr.internalTimeout, deviceMgr.rpcTimeout)
d, err := deviceAgent.start(context.TODO(), false, clonedDevice)
assert.Nil(t, err)
assert.NotNil(t, d)
@@ -215,19 +195,13 @@
deviceToUpdate.MacAddress = macAddress
deviceToUpdate.Vlan = vlan
deviceToUpdate.Reason = reason
+ deviceToUpdate.OperStatus = voltha.OperStatus_ACTIVE
+ deviceToUpdate.ConnectStatus = voltha.ConnectStatus_REACHABLE
err := da.updateDeviceUsingAdapterData(context.Background(), deviceToUpdate)
assert.Nil(t, err)
localWG.Done()
}()
- // Update the device status routine
- localWG.Add(1)
- go func() {
- err := da.updateDeviceStatus(context.Background(), voltha.OperStatus_ACTIVE, voltha.ConnectStatus_REACHABLE)
- assert.Nil(t, err)
- localWG.Done()
- }()
-
// Add a port routine
localWG.Add(1)
go func() {
@@ -253,8 +227,6 @@
updatedDevice, _ := da.getDeviceReadOnly(context.Background())
updatedDevicePorts := da.listDevicePorts()
assert.NotNil(t, updatedDevice)
- fmt.Printf("1 %+v\n", expectedChange)
- fmt.Printf("2 %+v\n", updatedDevice)
assert.True(t, proto.Equal(expectedChange, updatedDevice))
assert.Equal(t, len(originalDevicePorts)+1, len(updatedDevicePorts))
assert.True(t, proto.Equal(updatedDevicePorts[portToAdd.PortNo], portToAdd))
@@ -268,7 +240,7 @@
da := newDATest(ctx)
assert.NotNil(t, da)
defer da.stopAll(ctx)
- log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
+
// Start the Core
da.startCore(ctx)
@@ -279,7 +251,6 @@
a := da.createDeviceAgent(t)
go da.updateDeviceConcurrently(t, a, &wg)
}
-
wg.Wait()
}
}
@@ -292,8 +263,6 @@
log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
// Start the Core
da.startCore(ctx)
- da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(ctx, t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
-
a := da.createDeviceAgent(t)
err1 := a.requestQueue.WaitForGreenLight(ctx)
assert.Nil(t, err1)
@@ -312,7 +281,6 @@
// Start the Core
da.startCore(ctx)
- da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(ctx, t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
a := da.createDeviceAgent(t)
err1 := a.requestQueue.WaitForGreenLight(ctx)
assert.Nil(t, err1)
@@ -380,7 +348,9 @@
{Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
}
err := da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ // Expect specific error as adapter communication, for unit tests, are not set
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "flow-failure-device-"))
daFlows := changeToFlowList(da.listDeviceFlows())
assert.True(t, isFlowSliceEqual(newFlows, daFlows))
@@ -399,7 +369,8 @@
}
err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "flow-failure-device-"))
daFlows = changeToFlowList(da.listDeviceFlows())
assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
@@ -420,7 +391,8 @@
}
err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daFlows = changeToFlowList(da.listDeviceFlows())
assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
@@ -459,7 +431,8 @@
}
err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daFlows = changeToFlowList(da.listDeviceFlows())
assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
//Delete flows with an unexisting one
@@ -474,7 +447,8 @@
}
err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daFlows = changeToFlowList(da.listDeviceFlows())
assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
}
@@ -486,7 +460,8 @@
{Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
}
err := da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "flow-failure-device-"))
daGroups := changeToGroupList(da.listDeviceGroups())
assert.True(t, isGroupSliceEqual(newGroups, daGroups))
@@ -502,7 +477,8 @@
{Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
}
err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daGroups = changeToGroupList(da.listDeviceGroups())
assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
@@ -520,7 +496,8 @@
{Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
}
err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daGroups = changeToGroupList(da.listDeviceGroups())
assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
@@ -536,7 +513,8 @@
{Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
}
err = da.updateFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, updtGroups, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daGroups = changeToGroupList(da.listDeviceGroups())
assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
@@ -551,7 +529,8 @@
{Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
}
err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daGroups = changeToGroupList(da.listDeviceGroups())
assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
@@ -565,7 +544,49 @@
{Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
}
err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
- assert.Nil(t, err)
+ assert.NotNil(t, err)
+ assert.True(t, strings.Contains(err.Error(), "Aborted"))
daGroups = changeToGroupList(da.listDeviceGroups())
assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
}
+
+// registerAdapters registers the ONU and OLT adapters
+func (dat *DATest) registerAdapters(ctx context.Context) {
+ oltAdapter := &voltha.Adapter{
+ Id: "olt-mock-adapter-1",
+ Vendor: "olt-mock-vendor",
+ Version: ver.VersionInfo.Version,
+ Type: "olt-mock-adapter-type",
+ CurrentReplica: 1,
+ TotalReplicas: 1,
+ Endpoint: "mock-olt-endpoint",
+ }
+ types := []*voltha.DeviceType{{Id: "olt-mock-device-type", AdapterType: "olt-mock-adapter-type", AcceptsAddRemoveFlowUpdates: true}}
+ deviceTypes := &voltha.DeviceTypes{Items: types}
+ _, err := dat.adapterMgr.RegisterAdapter(ctx, &ic.AdapterRegistration{
+ Adapter: oltAdapter,
+ DTypes: deviceTypes,
+ })
+ if err != nil {
+ logger.Fatalw(ctx, "olt registration failed", log.Fields{"error": err})
+ }
+
+ onuAdapter := &voltha.Adapter{
+ Id: "onu-mock-adapter-1",
+ Vendor: "onu-mock-vendor",
+ Version: ver.VersionInfo.Version,
+ Type: "onu-mock-adapter-type",
+ CurrentReplica: 1,
+ TotalReplicas: 1,
+ Endpoint: "mock-onu-endpoint",
+ }
+ types = []*voltha.DeviceType{{Id: "onu-mock-device-type", AdapterType: "onu-mock-adapter-type", AcceptsAddRemoveFlowUpdates: true}}
+ deviceTypes = &voltha.DeviceTypes{Items: types}
+ _, err = dat.adapterMgr.RegisterAdapter(ctx, &ic.AdapterRegistration{
+ Adapter: onuAdapter,
+ DTypes: deviceTypes,
+ })
+ if err != nil {
+ logger.Fatalw(ctx, "onu registration failed", log.Fields{"error": err})
+ }
+}
diff --git a/rw_core/core/device/agent_transient_state.go b/rw_core/core/device/agent_transient_state.go
index 0adf57d..ea105dd 100644
--- a/rw_core/core/device/agent_transient_state.go
+++ b/rw_core/core/device/agent_transient_state.go
@@ -18,26 +18,28 @@
import (
"context"
- "github.com/opencord/voltha-protos/v4/go/common"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+
+ "github.com/opencord/voltha-protos/v5/go/common"
+ "github.com/opencord/voltha-protos/v5/go/core"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
-func (agent *Agent) getTransientState() voltha.DeviceTransientState_Types {
+func (agent *Agent) getTransientState() core.DeviceTransientState_Types {
transientStateHandle := agent.transientStateLoader.Lock()
deviceTransientState := transientStateHandle.GetReadOnly()
transientStateHandle.UnLock()
return deviceTransientState
}
-func (agent *Agent) matchTransientState(transientState voltha.DeviceTransientState_Types) bool {
+func (agent *Agent) matchTransientState(transientState core.DeviceTransientState_Types) bool {
transientStateHandle := agent.transientStateLoader.Lock()
defer transientStateHandle.UnLock()
return transientState == transientStateHandle.GetReadOnly()
}
-func (agent *Agent) updateTransientState(ctx context.Context, transientState voltha.DeviceTransientState_Types) error {
+func (agent *Agent) updateTransientState(ctx context.Context, transientState core.DeviceTransientState_Types) error {
// Already in same transientState
if transientState == agent.getTransientState() {
return nil
@@ -54,16 +56,17 @@
func (agent *Agent) isDeletionInProgress() bool {
deviceTransientState := agent.getTransientState()
- return deviceTransientState == voltha.DeviceTransientState_FORCE_DELETING ||
- deviceTransientState == voltha.DeviceTransientState_DELETING_FROM_ADAPTER ||
- deviceTransientState == voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE
+ return deviceTransientState == core.DeviceTransientState_FORCE_DELETING ||
+ deviceTransientState == core.DeviceTransientState_DELETING_FROM_ADAPTER ||
+ deviceTransientState == core.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE
}
-func (agent *Agent) isStateDeleting(deviceTransientState voltha.DeviceTransientState_Types) bool {
- return deviceTransientState == voltha.DeviceTransientState_FORCE_DELETING ||
- deviceTransientState == voltha.DeviceTransientState_DELETING_FROM_ADAPTER ||
- deviceTransientState == voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE
+func (agent *Agent) isForceDeletingAllowed(deviceTransientState core.DeviceTransientState_Types, device *voltha.Device) bool {
+ return deviceTransientState != core.DeviceTransientState_FORCE_DELETING &&
+ (device.OperStatus != common.OperStatus_RECONCILING ||
+ !agent.matchTransientState(core.DeviceTransientState_RECONCILE_IN_PROGRESS))
}
+
func (agent *Agent) deleteTransientState(ctx context.Context) error {
transientStateHandle := agent.transientStateLoader.Lock()
if err := transientStateHandle.Delete(ctx); err != nil {
@@ -76,5 +79,5 @@
func (agent *Agent) isInReconcileState(device *voltha.Device) bool {
return device.OperStatus == common.OperStatus_RECONCILING || device.OperStatus == common.OperStatus_RECONCILING_FAILED ||
- agent.matchTransientState(voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ agent.matchTransientState(core.DeviceTransientState_RECONCILE_IN_PROGRESS)
}
diff --git a/rw_core/core/device/common.go b/rw_core/core/device/common.go
index d781187..bad2067 100644
--- a/rw_core/core/device/common.go
+++ b/rw_core/core/device/common.go
@@ -18,7 +18,7 @@
package device
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/event/common.go b/rw_core/core/device/event/common.go
index 72d5077..7a0ca19 100644
--- a/rw_core/core/device/event/common.go
+++ b/rw_core/core/device/event/common.go
@@ -18,7 +18,7 @@
package event
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/event/event.go b/rw_core/core/device/event/event.go
index 2a134f1..d21995f 100644
--- a/rw_core/core/device/event/event.go
+++ b/rw_core/core/device/event/event.go
@@ -26,12 +26,12 @@
"github.com/golang/protobuf/ptypes/empty"
"github.com/opencord/voltha-go/rw_core/utils"
- ev "github.com/opencord/voltha-lib-go/v5/pkg/events"
- "github.com/opencord/voltha-lib-go/v5/pkg/events/eventif"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/common"
- "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ ev "github.com/opencord/voltha-lib-go/v7/pkg/events"
+ "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"github.com/opentracing/opentracing-go"
jtracing "github.com/uber/jaeger-client-go"
)
@@ -67,7 +67,7 @@
stackID: stackID,
}
}
-func (q *Manager) SendPacketIn(ctx context.Context, deviceID string, transationID string, packet *openflow_13.OfpPacketIn) {
+func (q *Manager) SendPacketIn(ctx context.Context, deviceID string, packet *openflow_13.OfpPacketIn) {
// TODO: Augment the OF PacketIn to include the transactionId
packetIn := openflow_13.PacketIn{Id: deviceID, PacketIn: packet}
logger.Debugw(ctx, "send-packet-in", log.Fields{"packet-in": packetIn})
@@ -273,7 +273,7 @@
//TODO Instead of directly sending to the kafka bus, queue the message and send it asynchronously
if rpcEvent.Rpc != "" {
if err := q.eventProxy.SendRPCEvent(ctx, id, rpcEvent, category, subCategory, raisedTs); err != nil {
- logger.Errorw(ctx, "failed-to-send-rpc-event", log.Fields{"resource-id": id})
+ logger.Errorw(ctx, "failed-to-send-rpc-event", log.Fields{"resource-id": id, "error": err})
}
}
}
@@ -283,7 +283,7 @@
rpcEvent := q.NewRPCEvent(ctx, resourceID, desc, context)
if rpcEvent.Rpc != "" {
if err := q.eventProxy.SendRPCEvent(ctx, id, rpcEvent, category, subCategory, raisedTs); err != nil {
- logger.Errorw(ctx, "failed-to-send-rpc-event", log.Fields{"resource-id": id})
+ logger.Errorw(ctx, "failed-to-send-rpc-event", log.Fields{"resource-id": id, "error": err})
}
}
}
diff --git a/rw_core/core/device/extension_manager.go b/rw_core/core/device/extension_manager.go
index 40c98aa..a895c34 100644
--- a/rw_core/core/device/extension_manager.go
+++ b/rw_core/core/device/extension_manager.go
@@ -18,8 +18,9 @@
import (
"context"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/extension"
+
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/extension"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
diff --git a/rw_core/core/device/flow/cache.go b/rw_core/core/device/flow/cache.go
index b4e358e..81efe0d 100644
--- a/rw_core/core/device/flow/cache.go
+++ b/rw_core/core/device/flow/cache.go
@@ -20,7 +20,7 @@
"context"
"sync"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
)
// Cache hides all low-level locking & synchronization related to flow state updates
diff --git a/rw_core/core/device/flow/common.go b/rw_core/core/device/flow/common.go
index 6672e01..5765c5d 100644
--- a/rw_core/core/device/flow/common.go
+++ b/rw_core/core/device/flow/common.go
@@ -18,7 +18,7 @@
package flow
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/group/cache.go b/rw_core/core/device/group/cache.go
index eb6a5a3..b182914 100644
--- a/rw_core/core/device/group/cache.go
+++ b/rw_core/core/device/group/cache.go
@@ -20,7 +20,7 @@
"context"
"sync"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
)
// Cache hides all low-level locking & synchronization related to group state updates
diff --git a/rw_core/core/device/logical_agent.go b/rw_core/core/device/logical_agent.go
index b9ad95a..cbf2625 100644
--- a/rw_core/core/device/logical_agent.go
+++ b/rw_core/core/device/logical_agent.go
@@ -26,16 +26,16 @@
"github.com/opencord/voltha-go/db/model"
"github.com/opencord/voltha-go/rw_core/core/device/flow"
"github.com/opencord/voltha-go/rw_core/core/device/group"
- "github.com/opencord/voltha-go/rw_core/core/device/logical_port"
+ lp "github.com/opencord/voltha-go/rw_core/core/device/logical_port"
"github.com/opencord/voltha-go/rw_core/core/device/meter"
fd "github.com/opencord/voltha-go/rw_core/flowdecomposition"
"github.com/opencord/voltha-go/rw_core/route"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ic "github.com/opencord/voltha-protos/v4/go/inter_container"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -51,7 +51,7 @@
stopped bool
deviceRoutes *route.DeviceRoutes
flowDecomposer *fd.FlowDecomposer
- defaultTimeout time.Duration
+ internalTimeout time.Duration
logicalDevice *voltha.LogicalDevice
requestQueue *coreutils.RequestQueue
orderedEvents orderedEvents
@@ -61,11 +61,11 @@
flowCache *flow.Cache
meterLoader *meter.Loader
groupCache *group.Cache
- portLoader *port.Loader
+ portLoader *lp.Loader
}
func newLogicalAgent(ctx context.Context, id string, sn string, deviceID string, ldeviceMgr *LogicalManager,
- deviceMgr *Manager, dbProxy *model.Path, ldProxy *model.Proxy, defaultTimeout time.Duration) *LogicalAgent {
+ deviceMgr *Manager, dbProxy *model.Path, ldProxy *model.Proxy, internalTimeout time.Duration) *LogicalAgent {
return &LogicalAgent{
logicalDeviceID: id,
serialNumber: sn,
@@ -75,13 +75,13 @@
ldeviceMgr: ldeviceMgr,
deviceRoutes: route.NewDeviceRoutes(id, deviceID, deviceMgr.listDevicePorts),
flowDecomposer: fd.NewFlowDecomposer(deviceMgr.getDeviceReadOnly),
- defaultTimeout: defaultTimeout,
+ internalTimeout: internalTimeout,
requestQueue: coreutils.NewRequestQueue(),
flowCache: flow.NewCache(),
groupCache: group.NewCache(),
meterLoader: meter.NewLoader(dbProxy.SubPath("logical_meters").Proxy(id)),
- portLoader: port.NewLoader(dbProxy.SubPath("logical_ports").Proxy(id)),
+ portLoader: lp.NewLoader(dbProxy.SubPath("logical_ports").Proxy(id)),
}
}
@@ -196,7 +196,7 @@
return
}
defer agent.requestQueue.RequestComplete()
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.internalTimeout)
// Before deletion of the logical agent, make sure all events for ldagent are sent to avoid race conditions
if err := agent.orderedEvents.waitForAllEventsToBeSent(subCtx, cancel); err != nil {
//Log the error here
@@ -236,7 +236,7 @@
response := coreutils.NewResponse()
responses = append(responses, response)
go func(deviceId string, value *fu.FlowsAndGroups) {
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.internalTimeout)
subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
defer cancel()
@@ -272,7 +272,7 @@
response := coreutils.NewResponse()
responses = append(responses, response)
go func(deviceId string, value *fu.FlowsAndGroups) {
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.internalTimeout)
subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
defer cancel()
@@ -306,7 +306,7 @@
response := coreutils.NewResponse()
responses = append(responses, response)
go func(deviceId string, value *fu.FlowsAndGroups) {
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.internalTimeout)
subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
defer cancel()
@@ -342,7 +342,7 @@
}
logger.Debugw(ctx, "uni-port", log.Fields{"flows": flows, "uni-port": uniPort})
go func(uniPort uint32, metadata *voltha.FlowMetadata) {
- subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
+ subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.internalTimeout)
subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
defer cancel()
@@ -375,16 +375,15 @@
}
}
-func (agent *LogicalAgent) packetIn(ctx context.Context, port uint32, transactionID string, packet []byte) {
+func (agent *LogicalAgent) packetIn(ctx context.Context, port uint32, packet []byte) {
if logger.V(log.InfoLevel) {
- logger.Debugw(ctx, "packet-in", log.Fields{
- "port": port,
- "packet": hex.EncodeToString(packet),
- "transactionId": transactionID,
+ logger.Infow(ctx, "packet-in", log.Fields{
+ "port": port,
+ "packet": hex.EncodeToString(packet),
})
}
packetIn := fu.MkPacketIn(port, packet)
- agent.ldeviceMgr.SendPacketIn(ctx, agent.logicalDeviceID, transactionID, packetIn)
+ agent.ldeviceMgr.SendPacketIn(ctx, agent.logicalDeviceID, packetIn)
logger.Debugw(ctx, "sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
}
diff --git a/rw_core/core/device/logical_agent_flow.go b/rw_core/core/device/logical_agent_flow.go
index 72b915f..85b78ef 100644
--- a/rw_core/core/device/logical_agent_flow.go
+++ b/rw_core/core/device/logical_agent_flow.go
@@ -24,12 +24,13 @@
"time"
"github.com/gogo/protobuf/proto"
+ "github.com/opencord/voltha-go/rw_core/core/device/flow"
"github.com/opencord/voltha-go/rw_core/route"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -104,7 +105,7 @@
var flowToReplace *ofp.OfpFlowStats
//if flow is not found in the map, create a new entry, otherwise get the existing one.
- flowHandle, created, err := agent.flowCache.LockOrCreate(ctx, flow)
+ flowHandle, flowCreated, err := agent.flowCache.LockOrCreate(ctx, flow)
if err != nil {
return changed, updated, err
}
@@ -122,7 +123,7 @@
changed = true
}
} else {
- if !created {
+ if !flowCreated {
flowToReplace = flowHandle.GetReadOnly()
if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
flow.ByteCount = flowToReplace.ByteCount
@@ -151,9 +152,30 @@
deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, updatedFlows, groups)
if err != nil {
+ if flowCreated {
+ if er := flowHandle.Delete(ctx); er != nil {
+ logger.Errorw(ctx, "deleting-flow-from-cache-failed", log.Fields{"error": er, "flow-id": flow.Id})
+ }
+ }
return changed, updated, err
}
+ // Verify whether the flow request can proceed, usually to multiple adapters
+ // This is an optimization to address the case where a decomposed set of flows need to
+ // be sent to multiple adapters. One or more adapters may not be ready at this time.
+ // If one adapter is not ready this will result in flows being reverted from the
+ // other adapters, at times continuously as the OF controller will keep sending the
+ // flows until they are successfully added.
+ if err := agent.deviceMgr.canMultipleAdapterRequestProceed(ctx, deviceRules.Keys()); err != nil {
+ logger.Warnw(ctx, "adapters-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "flow-id": flow.Id, "error": err})
+ if flowCreated {
+ if er := flowHandle.Delete(ctx); er != nil {
+ logger.Errorw(ctx, "deleting-flow-from-cache-failed", log.Fields{"error": er, "flow-id": flow.Id})
+ }
+ }
+ return false, false, err
+ }
+
logger.Debugw(ctx, "rules", log.Fields{"rules": deviceRules.String()})
// Update store and cache
if updated {
@@ -166,7 +188,7 @@
// Create the go routines to wait
go func() {
// Wait for completion
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChannels...); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, respChannels...); res != nil {
logger.Errorw(ctx, "failed-to-add-flow-will-attempt-deletion", log.Fields{
"errors": res,
"logical-device-id": agent.logicalDeviceID,
@@ -237,7 +259,7 @@
// Wait for the responses
go func() {
// Since this action is taken following an add failure, we may also receive a failure for the revert
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, respChnls...); res != nil {
logger.Warnw(ctx, "failure-reverting-added-flows", log.Fields{
"logical-device-id": agent.logicalDeviceID,
"flow-cookie": mod.Cookie,
@@ -327,6 +349,18 @@
partialRoute = true
}
+ var devicesInFlows []string
+ if deviceRules != nil {
+ devicesInFlows = deviceRules.Keys()
+ } else {
+ devicesInFlows = []string{agent.rootDeviceID}
+ }
+
+ if err := agent.deviceMgr.canMultipleAdapterRequestProceed(ctx, devicesInFlows); err != nil {
+ logger.Warnw(ctx, "adapters-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "flow": toDelete, "error": err})
+ return err
+ }
+
// Update the devices
if partialRoute {
respChnls = agent.deleteFlowsFromParentDevice(ctx, toDelete, mod)
@@ -337,7 +371,7 @@
// Wait for the responses
go func() {
// Wait for completion
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, respChnls...); res != nil {
logger.Errorw(ctx, "failure-updating-device-flows", log.Fields{"logical-device-id": agent.logicalDeviceID, "errors": res})
context := make(map[string]string)
context["rpc"] = coreutils.GetRPCMetadataFromContext(ctx)
@@ -363,6 +397,9 @@
//flowDeleteStrict deletes a flow from the flow table of that logical device
func (agent *LogicalAgent) flowDeleteStrict(ctx context.Context, flowUpdate *ofp.FlowTableUpdate) error {
+ var flowHandle *flow.Handle
+ var have bool
+
mod := flowUpdate.FlowMod
logger.Debugw(ctx, "flow-delete-strict", log.Fields{"mod": mod})
if mod == nil {
@@ -373,13 +410,18 @@
if err != nil {
return err
}
+
+ defer func() {
+ if flowHandle != nil {
+ flowHandle.Unlock()
+ }
+ }()
+
logger.Debugw(ctx, "flow-id-in-flow-delete-strict", log.Fields{"flow-id": flow.Id})
- flowHandle, have := agent.flowCache.Lock(flow.Id)
+ flowHandle, have = agent.flowCache.Lock(flow.Id)
if !have {
- logger.Debugw(ctx, "skipping-flow-delete-strict-request-no-flow-found", log.Fields{"flow-mod": mod})
- return nil
+ logger.Debugw(ctx, "flow-delete-strict-request-no-flow-found-continuing", log.Fields{"flow-mod": mod})
}
- defer flowHandle.Unlock()
groups := make(map[uint32]*ofp.OfpGroupEntry)
for groupID := range agent.groupCache.ListIDs() {
@@ -389,12 +431,11 @@
}
}
- if changedMeter := agent.updateFlowCountOfMeterStats(ctx, mod, flow, false); !changedMeter {
- return fmt.Errorf("Cannot delete flow - %s. Meter update failed", flow)
+ flowsToDelete := map[uint64]*ofp.OfpFlowStats{flow.Id: flow}
+ if flowHandle != nil {
+ flowsToDelete = map[uint64]*ofp.OfpFlowStats{flow.Id: flowHandle.GetReadOnly()}
}
- flowsToDelete := map[uint64]*ofp.OfpFlowStats{flow.Id: flowHandle.GetReadOnly()}
-
var respChnls []coreutils.Response
var partialRoute bool
deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, flowsToDelete, groups)
@@ -408,10 +449,18 @@
partialRoute = true
}
- // Update the model
- if err := flowHandle.Delete(ctx); err != nil {
+ var devicesInFlows []string
+ if deviceRules != nil {
+ devicesInFlows = deviceRules.Keys()
+ } else {
+ devicesInFlows = []string{agent.rootDeviceID}
+ }
+
+ if err := agent.deviceMgr.canMultipleAdapterRequestProceed(ctx, devicesInFlows); err != nil {
+ logger.Warnw(ctx, "adapters-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "flow": flowsToDelete, "error": err})
return err
}
+
// Update the devices
if partialRoute {
respChnls = agent.deleteFlowsFromParentDevice(ctx, flowsToDelete, mod)
@@ -420,30 +469,39 @@
}
// Wait for completion
- go func() {
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
- logger.Warnw(ctx, "failure-deleting-device-flows", log.Fields{
- "flow-cookie": mod.Cookie,
- "logical-device-id": agent.logicalDeviceID,
- "errors": res,
- })
- // TODO: Revert flow changes
- // send event, and allow any queued events to be sent as well
- agent.ldeviceMgr.SendFlowChangeEvent(ctx, agent.logicalDeviceID, res, flowUpdate.Xid, flowUpdate.FlowMod.Cookie)
- context := make(map[string]string)
- context["rpc"] = coreutils.GetRPCMetadataFromContext(ctx)
- context["flow-id"] = fmt.Sprintf("%v", flow.Id)
- context["flow-cookie"] = fmt.Sprintf("%v", flowUpdate.FlowMod.Cookie)
- context["logical-device-id"] = agent.logicalDeviceID
- if deviceRules != nil {
- context["device-rules"] = deviceRules.String()
- }
- // Create context and send extra information as part of it.
- agent.ldeviceMgr.SendRPCEvent(ctx,
- agent.logicalDeviceID, "failed-to-delete-device-flows", context, "RPC_ERROR_RAISE_EVENT",
- voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, respChnls...); res != nil {
+ logger.Warnw(ctx, "failure-deleting-device-flows", log.Fields{
+ "flow-cookie": mod.Cookie,
+ "logical-device-id": agent.logicalDeviceID,
+ "errors": res,
+ })
+ context := make(map[string]string)
+ context["rpc"] = coreutils.GetRPCMetadataFromContext(ctx)
+ context["flow-id"] = fmt.Sprintf("%v", flow.Id)
+ context["flow-cookie"] = fmt.Sprintf("%v", flowUpdate.FlowMod.Cookie)
+ context["logical-device-id"] = agent.logicalDeviceID
+ if deviceRules != nil {
+ context["device-rules"] = deviceRules.String()
}
- }()
+ // Create context and send extra information as part of it.
+ agent.ldeviceMgr.SendRPCEvent(ctx,
+ agent.logicalDeviceID, "failed-to-delete-device-flows", context, "RPC_ERROR_RAISE_EVENT",
+ voltha.EventCategory_COMMUNICATION, nil, time.Now().Unix())
+
+ return status.Errorf(codes.Aborted, "failed deleting flows id:%d, errors:%v", flow.Id, res)
+ }
+
+ // Update meter count
+ if changedMeter := agent.updateFlowCountOfMeterStats(ctx, mod, flow, false); !changedMeter {
+ return fmt.Errorf("cannot delete flow - %s. Meter update failed", flow)
+ }
+
+ // Update the model
+ if flowHandle != nil {
+ if err := flowHandle.Delete(ctx); err != nil {
+ return err
+ }
+ }
return nil
}
diff --git a/rw_core/core/device/logical_agent_group.go b/rw_core/core/device/logical_agent_group.go
index c778aa5..9a47d81 100644
--- a/rw_core/core/device/logical_agent_group.go
+++ b/rw_core/core/device/logical_agent_group.go
@@ -22,10 +22,10 @@
"time"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -91,7 +91,7 @@
// Wait for completion
go func() {
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, respChnls...); res != nil {
logger.Warnw(ctx, "failure-updating-device-flows-groups", log.Fields{"logical-device-id": agent.logicalDeviceID, "errors": res})
context := make(map[string]string)
context["rpc"] = coreutils.GetRPCMetadataFromContext(ctx)
@@ -163,6 +163,7 @@
deviceRules = fu.NewDeviceRules()
deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
}
+
//add groups to deviceRules
for _, groupEntry := range affectedGroups {
fg := fu.NewFlowsAndGroups()
@@ -171,12 +172,17 @@
}
logger.Debugw(ctx, "rules", log.Fields{"rules": deviceRules.String()})
+ if err := agent.deviceMgr.canMultipleAdapterRequestProceed(ctx, deviceRules.Keys()); err != nil {
+ logger.Warnw(ctx, "adapters-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
+ return err
+ }
+
// delete groups and related flows, if any
respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &ofp.OfpFlowMod{})
// Wait for completion
go func() {
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, respChnls...); res != nil {
logger.Warnw(ctx, "failure-updating-device-flows-groups", log.Fields{"logical-device-id": agent.logicalDeviceID, "errors": res})
context := make(map[string]string)
context["rpc"] = coreutils.GetRPCMetadataFromContext(ctx)
@@ -229,7 +235,7 @@
// Wait for completion
go func() {
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, respChnls...); res != nil {
logger.Warnw(ctx, "failure-updating-device-flows-groups", log.Fields{"logical-device-id": agent.logicalDeviceID, "errors": res})
context := make(map[string]string)
context["rpc"] = coreutils.GetRPCMetadataFromContext(ctx)
diff --git a/rw_core/core/device/logical_agent_meter.go b/rw_core/core/device/logical_agent_meter.go
index 7e824d2..f26a8bd 100644
--- a/rw_core/core/device/logical_agent_meter.go
+++ b/rw_core/core/device/logical_agent_meter.go
@@ -20,9 +20,9 @@
"context"
"fmt"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
diff --git a/rw_core/core/device/logical_agent_meter_helpers.go b/rw_core/core/device/logical_agent_meter_helpers.go
index 19f7aad..16f7302 100644
--- a/rw_core/core/device/logical_agent_meter_helpers.go
+++ b/rw_core/core/device/logical_agent_meter_helpers.go
@@ -20,9 +20,9 @@
"context"
"fmt"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
)
// GetMeterConfig returns meters which which are used by the given flows
diff --git a/rw_core/core/device/logical_agent_port.go b/rw_core/core/device/logical_agent_port.go
index 4672aca..35f18b9 100644
--- a/rw_core/core/device/logical_agent_port.go
+++ b/rw_core/core/device/logical_agent_port.go
@@ -22,10 +22,10 @@
"sync"
coreutils "github.com/opencord/voltha-go/rw_core/utils"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -93,7 +93,7 @@
}
// Now, set up the UNI ports if needed.
- children, err := agent.deviceMgr.GetAllChildDevices(ctx, agent.rootDeviceID)
+ children, err := agent.deviceMgr.getAllChildDevices(ctx, agent.rootDeviceID)
if err != nil {
logger.Errorw(ctx, "error-getting-child-devices", log.Fields{"error": err, "device-id": agent.rootDeviceID})
return err
@@ -120,7 +120,7 @@
}(subCtx, child)
}
// Wait for completion
- if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
+ if res := coreutils.WaitForNilOrErrorResponses(agent.internalTimeout, responses...); res != nil {
return status.Errorf(codes.Aborted, "errors-%s", res)
}
return nil
@@ -220,8 +220,8 @@
// Reset the logical device routes
go func() {
subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
- if err := agent.buildRoutes(subCtx); err != nil {
- logger.Warnw(ctx, "device-routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
+ if err := agent.removeRoutes(subCtx); err != nil {
+ logger.Warnw(ctx, "error-removing-routes", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
}
}()
return nil
@@ -513,16 +513,16 @@
// getUNILogicalPortNo returns the UNI logical port number specified in the flow
func (agent *LogicalAgent) getUNILogicalPortNo(flow *ofp.OfpFlowStats) (uint32, error) {
- var uniPort uint32
inPortNo := fu.GetInPort(flow)
outPortNo := fu.GetOutPort(flow)
- if agent.isNNIPort(inPortNo) {
- uniPort = outPortNo
- } else if agent.isNNIPort(outPortNo) {
- uniPort = inPortNo
+ if inPortNo == 0 && outPortNo == 0 {
+ return 0, status.Errorf(codes.NotFound, "no-uni-port: %v", flow)
}
- if uniPort != 0 {
- return uniPort, nil
+ if inPortNo != 0 && !agent.isNNIPort(inPortNo) {
+ return inPortNo, nil
+ }
+ if outPortNo != 0 && !agent.isNNIPort(outPortNo) {
+ return outPortNo, nil
}
return 0, status.Errorf(codes.NotFound, "no-uni-port: %v", flow)
}
diff --git a/rw_core/core/device/logical_agent_route.go b/rw_core/core/device/logical_agent_route.go
index 102397f..333efa8 100644
--- a/rw_core/core/device/logical_agent_route.go
+++ b/rw_core/core/device/logical_agent_route.go
@@ -21,9 +21,9 @@
"fmt"
"github.com/opencord/voltha-go/rw_core/route"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
)
// GetRoute returns a route
@@ -107,6 +107,17 @@
return nil
}
+func (agent *LogicalAgent) removeRoutes(ctx context.Context) error {
+ if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+ return err
+ }
+ defer agent.requestQueue.RequestComplete()
+
+ agent.deviceRoutes.RemoveRoutes()
+
+ return nil
+}
+
//updateRoutes updates the device routes
func (agent *LogicalAgent) updateRoutes(ctx context.Context, deviceID string, devicePorts map[uint32]*voltha.Port, lp *voltha.LogicalPort, lps map[uint32]*voltha.LogicalPort) error {
logger.Debugw(ctx, "updateRoutes", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-id": deviceID, "port:": lp})
diff --git a/rw_core/core/device/logical_agent_test.go b/rw_core/core/device/logical_agent_test.go
index 8114dd0..e611019 100644
--- a/rw_core/core/device/logical_agent_test.go
+++ b/rw_core/core/device/logical_agent_test.go
@@ -28,15 +28,15 @@
"github.com/opencord/voltha-go/rw_core/config"
"github.com/opencord/voltha-go/rw_core/core/adapter"
tst "github.com/opencord/voltha-go/rw_core/test"
- com "github.com/opencord/voltha-lib-go/v5/pkg/adapters/common"
- "github.com/opencord/voltha-lib-go/v5/pkg/db"
- "github.com/opencord/voltha-lib-go/v5/pkg/events"
- fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- mock_etcd "github.com/opencord/voltha-lib-go/v5/pkg/mocks/etcd"
- mock_kafka "github.com/opencord/voltha-lib-go/v5/pkg/mocks/kafka"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ com "github.com/opencord/voltha-lib-go/v7/pkg/adapters/common"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db"
+ "github.com/opencord/voltha-lib-go/v7/pkg/events"
+ fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
+ "github.com/opencord/voltha-lib-go/v7/pkg/kafka"
+ mock_etcd "github.com/opencord/voltha-lib-go/v7/pkg/mocks/etcd"
+ mock_kafka "github.com/opencord/voltha-lib-go/v7/pkg/mocks/kafka"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"github.com/phayes/freeport"
"github.com/stretchr/testify/assert"
)
@@ -44,7 +44,6 @@
type LDATest struct {
etcdServer *mock_etcd.EtcdServer
deviceMgr *Manager
- kmp kafka.InterContainerProxy
logicalDeviceMgr *LogicalManager
kClient kafka.Client
kEventClient kafka.Client
@@ -52,8 +51,8 @@
oltAdapterName string
onuAdapterName string
coreInstanceID string
- defaultTimeout time.Duration
- maxTimeout time.Duration
+ internalTimeout time.Duration
+ rpcTimeout time.Duration
logicalDevice *voltha.LogicalDevice
logicalPorts map[uint32]*voltha.LogicalPort
deviceIds []string
@@ -74,8 +73,8 @@
test.oltAdapterName = "olt_adapter_mock"
test.onuAdapterName = "onu_adapter_mock"
test.coreInstanceID = "rw-da-test"
- test.defaultTimeout = 5 * time.Second
- test.maxTimeout = 20 * time.Second
+ test.internalTimeout = 5 * time.Second
+ test.rpcTimeout = 20 * time.Second
test.done = make(chan int)
test.deviceIds = []string{com.GetRandomString(10), com.GetRandomString(10), com.GetRandomString(10)}
test.logicalDevice = &voltha.LogicalDevice{
@@ -138,15 +137,14 @@
func (lda *LDATest) startCore(ctx context.Context, inCompeteMode bool) {
cfg := &config.RWCoreFlags{}
cfg.ParseCommandArguments([]string{})
- cfg.CoreTopic = "rw_core"
cfg.EventTopic = "voltha.events"
- cfg.DefaultRequestTimeout = lda.defaultTimeout
+ cfg.InternalTimeout = lda.internalTimeout
cfg.KVStoreAddress = "127.0.0.1" + ":" + strconv.Itoa(lda.kvClientPort)
grpcPort, err := freeport.GetFreePort()
if err != nil {
logger.Fatal(ctx, "Cannot get a freeport for grpc")
}
- cfg.GrpcAddress = "127.0.0.1" + ":" + strconv.Itoa(grpcPort)
+ cfg.GrpcNBIAddress = "127.0.0.1" + ":" + strconv.Itoa(grpcPort)
client := tst.SetupKVClient(ctx, cfg, lda.coreInstanceID)
backend := &db.Backend{
Client: client,
@@ -154,29 +152,18 @@
Address: cfg.KVStoreAddress,
Timeout: cfg.KVStoreTimeout,
LivenessChannelInterval: cfg.LiveProbeInterval / 2}
- lda.kmp = kafka.NewInterContainerProxy(
- kafka.InterContainerAddress(cfg.KafkaAdapterAddress),
- kafka.MsgClient(lda.kClient),
- kafka.DefaultTopic(&kafka.Topic{Name: cfg.CoreTopic}))
- endpointMgr := kafka.NewEndpointManager(backend)
proxy := model.NewDBPath(backend)
- adapterMgr := adapter.NewAdapterManager(ctx, proxy, lda.coreInstanceID, lda.kClient)
+ adapterMgr := adapter.NewAdapterManager(proxy, lda.coreInstanceID, backend, 5)
eventProxy := events.NewEventProxy(events.MsgClient(lda.kEventClient), events.MsgTopic(kafka.Topic{Name: cfg.EventTopic}))
- lda.deviceMgr, lda.logicalDeviceMgr = NewManagers(proxy, adapterMgr, lda.kmp, endpointMgr, cfg, lda.coreInstanceID, eventProxy)
- if err = lda.kmp.Start(ctx); err != nil {
- logger.Fatal(ctx, "Cannot start InterContainerProxy")
- }
- adapterMgr.Start(context.Background())
+ lda.deviceMgr, lda.logicalDeviceMgr = NewManagers(proxy, adapterMgr, cfg, lda.coreInstanceID, eventProxy)
+ adapterMgr.Start(context.Background(), "logical-test")
}
func (lda *LDATest) stopAll(ctx context.Context) {
if lda.kClient != nil {
lda.kClient.Stop(ctx)
}
- if lda.kmp != nil {
- lda.kmp.Stop(ctx)
- }
if lda.etcdServer != nil {
tst.StopEmbeddedEtcdServer(ctx, lda.etcdServer)
}
@@ -191,7 +178,7 @@
clonedLD := proto.Clone(lda.logicalDevice).(*voltha.LogicalDevice)
clonedLD.Id = com.GetRandomString(10)
clonedLD.DatapathId = rand.Uint64()
- lDeviceAgent := newLogicalAgent(context.Background(), clonedLD.Id, clonedLD.Id, clonedLD.RootDeviceId, lDeviceMgr, deviceMgr, lDeviceMgr.dbPath, lDeviceMgr.ldProxy, lDeviceMgr.defaultTimeout)
+ lDeviceAgent := newLogicalAgent(context.Background(), clonedLD.Id, clonedLD.Id, clonedLD.RootDeviceId, lDeviceMgr, deviceMgr, lDeviceMgr.dbPath, lDeviceMgr.ldProxy, lDeviceMgr.internalTimeout)
lDeviceAgent.logicalDevice = clonedLD
for _, port := range lda.logicalPorts {
clonedPort := proto.Clone(port).(*voltha.LogicalPort)
diff --git a/rw_core/core/device/logical_manager.go b/rw_core/core/device/logical_manager.go
index 26021ca..def6dc9 100644
--- a/rw_core/core/device/logical_manager.go
+++ b/rw_core/core/device/logical_manager.go
@@ -19,21 +19,21 @@
import (
"context"
"errors"
- "github.com/opencord/voltha-lib-go/v5/pkg/probe"
"io"
"strconv"
"strings"
"sync"
"time"
+ "github.com/opencord/voltha-lib-go/v7/pkg/probe"
+
"github.com/golang/protobuf/ptypes/empty"
"github.com/opencord/voltha-go/db/model"
"github.com/opencord/voltha-go/rw_core/core/device/event"
"github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -43,26 +43,25 @@
*event.Manager
logicalDeviceAgents sync.Map
deviceMgr *Manager
- kafkaICProxy kafka.InterContainerProxy
dbPath *model.Path
ldProxy *model.Proxy
- defaultTimeout time.Duration
+ internalTimeout time.Duration
logicalDevicesLoadingLock sync.RWMutex
logicalDeviceLoadingInProgress map[string][]chan int
}
-func (ldMgr *LogicalManager) Start(ctx context.Context) {
+func (ldMgr *LogicalManager) Start(ctx context.Context, serviceName string) {
logger.Info(ctx, "starting-logical-device-manager")
- probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusPreparing)
+ probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusPreparing)
// Load all the logical devices from the dB
var logicalDevices []*voltha.LogicalDevice
if err := ldMgr.ldProxy.List(ctx, &logicalDevices); err != nil {
- logger.Fatalw(ctx, "failed-to-list-logical-devices-from-cluster-proxy", log.Fields{"error": err})
+ logger.Fatalw(ctx, "failed-to-list-logical-devices-from-cluster-proxy", log.Fields{"error": err, "service-name": serviceName})
}
for _, lDevice := range logicalDevices {
// Create an agent for each device
- agent := newLogicalAgent(ctx, lDevice.Id, "", "", ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.defaultTimeout)
+ agent := newLogicalAgent(ctx, lDevice.Id, "", "", ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.internalTimeout)
if err := agent.start(ctx, true, lDevice); err != nil {
logger.Warnw(ctx, "failure-starting-logical-agent", log.Fields{"logical-device-id": lDevice.Id})
} else {
@@ -70,7 +69,7 @@
}
}
- probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusRunning)
+ probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
logger.Info(ctx, "logical-device-manager-started")
}
@@ -128,7 +127,9 @@
var logicalDevices []*voltha.LogicalDevice
ldMgr.logicalDeviceAgents.Range(func(key, value interface{}) bool {
if ld, err := value.(*LogicalAgent).GetLogicalDeviceReadOnly(ctx); err == nil {
- logicalDevices = append(logicalDevices, ld)
+ if ld != nil {
+ logicalDevices = append(logicalDevices, ld)
+ }
} else {
logger.Errorw(ctx, "unable-to-get-logical-device", log.Fields{"err": err})
}
@@ -159,7 +160,7 @@
logger.Debugw(ctx, "logical-device-id", log.Fields{"logical-device-id": id})
- agent := newLogicalAgent(ctx, id, sn, device.Id, ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.defaultTimeout)
+ agent := newLogicalAgent(ctx, id, sn, device.Id, ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.internalTimeout)
ldMgr.addLogicalDeviceAgentToMap(agent)
// Update the root device with the logical device Id reference
@@ -232,7 +233,7 @@
ldMgr.logicalDevicesLoadingLock.Unlock()
if _, err := ldMgr.getLogicalDeviceFromModel(ctx, lDeviceID); err == nil {
logger.Debugw(ctx, "loading-logical-device", log.Fields{"lDeviceId": lDeviceID})
- agent := newLogicalAgent(ctx, lDeviceID, "", "", ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.defaultTimeout)
+ agent := newLogicalAgent(ctx, lDeviceID, "", "", ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.internalTimeout)
if err := agent.start(ctx, true, nil); err != nil {
return err
}
@@ -562,10 +563,10 @@
return &empty.Empty{}, agent.disableLogicalPort(ctx, uint32(portNo))
}
-func (ldMgr *LogicalManager) packetIn(ctx context.Context, logicalDeviceID string, port uint32, transactionID string, packet []byte) error {
+func (ldMgr *LogicalManager) packetIn(ctx context.Context, logicalDeviceID string, port uint32, packet []byte) error {
logger.Debugw(ctx, "packet-in", log.Fields{"logical-device-id": logicalDeviceID, "port": port})
if agent := ldMgr.getLogicalDeviceAgent(ctx, logicalDeviceID); agent != nil {
- agent.packetIn(ctx, port, transactionID, packet)
+ agent.packetIn(ctx, port, packet)
} else {
logger.Error(ctx, "logical-device-not-exist", log.Fields{"logical-device-id": logicalDeviceID})
}
diff --git a/rw_core/core/device/logical_port/common.go b/rw_core/core/device/logical_port/common.go
index fede329..c8b3538 100644
--- a/rw_core/core/device/logical_port/common.go
+++ b/rw_core/core/device/logical_port/common.go
@@ -18,7 +18,7 @@
package port
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/logical_port/loader.go b/rw_core/core/device/logical_port/loader.go
index 3117743..c6f272d 100644
--- a/rw_core/core/device/logical_port/loader.go
+++ b/rw_core/core/device/logical_port/loader.go
@@ -22,8 +22,8 @@
"sync"
"github.com/opencord/voltha-go/db/model"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
diff --git a/rw_core/core/device/manager.go b/rw_core/core/device/manager.go
index 0b34bfb..5519cab 100755
--- a/rw_core/core/device/manager.go
+++ b/rw_core/core/device/manager.go
@@ -18,27 +18,24 @@
import (
"context"
- "errors"
- "github.com/opencord/voltha-go/rw_core/config"
- "github.com/opencord/voltha-lib-go/v5/pkg/probe"
+ "fmt"
"sync"
"time"
- "github.com/golang/protobuf/ptypes/empty"
+ "github.com/opencord/voltha-go/rw_core/config"
+ "github.com/opencord/voltha-lib-go/v7/pkg/probe"
+ "github.com/opencord/voltha-protos/v5/go/core"
+
"github.com/opencord/voltha-go/db/model"
"github.com/opencord/voltha-go/rw_core/core/adapter"
"github.com/opencord/voltha-go/rw_core/core/device/event"
- "github.com/opencord/voltha-go/rw_core/core/device/remote"
"github.com/opencord/voltha-go/rw_core/core/device/state"
"github.com/opencord/voltha-go/rw_core/utils"
- "github.com/opencord/voltha-lib-go/v5/pkg/events"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/common"
- ic "github.com/opencord/voltha-protos/v4/go/inter_container"
- "github.com/opencord/voltha-protos/v4/go/openflow_13"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/events"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -48,32 +45,30 @@
deviceAgents sync.Map
rootDevices map[string]bool
lockRootDeviceMap sync.RWMutex
- adapterProxy *remote.AdapterProxy
*event.Agent
adapterMgr *adapter.Manager
logicalDeviceMgr *LogicalManager
- kafkaICProxy kafka.InterContainerProxy
stateTransitions *state.TransitionMap
dbPath *model.Path
dProxy *model.Proxy
coreInstanceID string
- defaultTimeout time.Duration
+ internalTimeout time.Duration
+ rpcTimeout time.Duration
devicesLoadingLock sync.RWMutex
deviceLoadingInProgress map[string][]chan int
config *config.RWCoreFlags
}
//NewManagers creates the Manager and the Logical Manager.
-func NewManagers(dbPath *model.Path, adapterMgr *adapter.Manager, kmp kafka.InterContainerProxy, endpointMgr kafka.EndpointManager, cf *config.RWCoreFlags, coreInstanceID string, eventProxy *events.EventProxy) (*Manager, *LogicalManager) {
+func NewManagers(dbPath *model.Path, adapterMgr *adapter.Manager, cf *config.RWCoreFlags, coreInstanceID string, eventProxy *events.EventProxy) (*Manager, *LogicalManager) {
deviceMgr := &Manager{
rootDevices: make(map[string]bool),
- kafkaICProxy: kmp,
- adapterProxy: remote.NewAdapterProxy(kmp, cf.CoreTopic, endpointMgr),
coreInstanceID: coreInstanceID,
dbPath: dbPath,
dProxy: dbPath.Proxy("devices"),
adapterMgr: adapterMgr,
- defaultTimeout: cf.DefaultCoreTimeout,
+ internalTimeout: cf.InternalTimeout,
+ rpcTimeout: cf.RPCTimeout,
Agent: event.NewAgent(eventProxy, coreInstanceID, cf.VolthaStackID),
deviceLoadingInProgress: make(map[string][]chan int),
config: cf,
@@ -83,33 +78,40 @@
logicalDeviceMgr := &LogicalManager{
Manager: event.NewManager(eventProxy, coreInstanceID, cf.VolthaStackID),
deviceMgr: deviceMgr,
- kafkaICProxy: kmp,
dbPath: dbPath,
ldProxy: dbPath.Proxy("logical_devices"),
- defaultTimeout: cf.DefaultCoreTimeout,
+ internalTimeout: cf.InternalTimeout,
logicalDeviceLoadingInProgress: make(map[string][]chan int),
}
deviceMgr.logicalDeviceMgr = logicalDeviceMgr
- adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
+ adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestartedHandler)
return deviceMgr, logicalDeviceMgr
}
-func (dMgr *Manager) Start(ctx context.Context) {
+func (dMgr *Manager) Start(ctx context.Context, serviceName string) error {
logger.Info(ctx, "starting-device-manager")
- probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusPreparing)
+ probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusPreparing)
// Load all the devices from the dB
var devices []*voltha.Device
if err := dMgr.dProxy.List(ctx, &devices); err != nil {
// Any error from the dB means if we proceed we may end up with corrupted data
- logger.Fatalw(ctx, "failed-to-list-devices-from-KV", log.Fields{"error": err})
+ logger.Errorw(ctx, "failed-to-list-devices-from-KV", log.Fields{"error": err, "service-name": serviceName})
+ return err
+ }
+
+ defer probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
+
+ if len(devices) == 0 {
+ logger.Info(ctx, "no-device-to-load")
+ return nil
}
for _, device := range devices {
// Create an agent for each device
- agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
+ agent := newAgent(device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout)
if _, err := agent.start(ctx, true, device); err != nil {
logger.Warnw(ctx, "failure-starting-agent", log.Fields{"device-id": device.Id})
} else {
@@ -119,8 +121,9 @@
// TODO: Need to trigger a reconcile at this point
- probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
logger.Info(ctx, "device-manager-started")
+
+ return nil
}
func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
@@ -172,165 +175,6 @@
return result
}
-// CreateDevice creates a new parent device in the data model
-func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
- if device.MacAddress == "" && device.GetHostAndPort() == "" {
- logger.Errorf(ctx, "no-device-info-present")
- return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
- }
- ctx = utils.WithRPCMetadataContext(ctx, "CreateDevice")
- logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
-
- deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
- if err != nil {
- logger.Errorf(ctx, "failed-to-fetch-parent-device-info")
- return nil, err
- }
- if deviceExist {
- logger.Errorf(ctx, "device-is-pre-provisioned-already-with-same-ip-port-or-mac-address")
- return nil, errors.New("device is already pre-provisioned")
- }
- logger.Debugw(ctx, "create-device", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
-
- // Ensure this device is set as root
- device.Root = true
- // Create and start a device agent for that device
- agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
- device, err = agent.start(ctx, false, device)
- if err != nil {
- logger.Errorw(ctx, "fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
- return nil, err
- }
- dMgr.addDeviceAgentToMap(agent)
- return device, nil
-}
-
-// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
-func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "EnableDevice")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "enable-device", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", id.Id)
- }
- return &empty.Empty{}, agent.enableDevice(ctx)
-}
-
-// DisableDevice disables a device along with any child device it may have
-func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "DisableDevice")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "disable-device", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", id.Id)
- }
- return &empty.Empty{}, agent.disableDevice(ctx)
-}
-
-//RebootDevice invoked the reboot API to the corresponding adapter
-func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "RebootDevice")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", id.Id)
- }
- return &empty.Empty{}, agent.rebootDevice(ctx)
-}
-
-// DeleteDevice removes a device from the data model
-func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "DeleteDevice")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "delete-device", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", id.Id)
- }
- return &empty.Empty{}, agent.deleteDevice(ctx)
-}
-
-// ForceDeleteDevice removes a device from the data model forcefully without successfully waiting for the adapters.
-func (dMgr *Manager) ForceDeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ForceDeleteDevice")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "force-delete-device", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", id.Id)
- }
- return &empty.Empty{}, agent.deleteDeviceForce(ctx)
-}
-
-// GetDevicePort returns the port details for a specific device port entry
-func (dMgr *Manager) GetDevicePort(ctx context.Context, deviceID string, portID uint32) (*voltha.Port, error) {
- logger.Debugw(ctx, "get-device-port", log.Fields{"device-id": deviceID})
- agent := dMgr.getDeviceAgent(ctx, deviceID)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "device-%s", deviceID)
- }
- return agent.getDevicePort(portID)
-}
-
-// ListDevicePorts returns the ports details for a specific device entry
-func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePorts")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
- }
-
- ports := agent.listDevicePorts()
- ctr, ret := 0, make([]*voltha.Port, len(ports))
- for _, port := range ports {
- ret[ctr] = port
- ctr++
- }
- return &voltha.Ports{Items: ret}, nil
-}
-
-// ListDeviceFlows returns the flow details for a specific device entry
-func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlows")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "list-device-flows", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
- }
-
- flows := agent.listDeviceFlows()
- ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
- for _, flow := range flows {
- ret[ctr] = flow
- ctr++
- }
- return &openflow_13.Flows{Items: ret}, nil
-}
-
-// ListDeviceFlowGroups returns the flow group details for a specific device entry
-func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlowGroups")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "list-device-flow-groups", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
- }
- groups := agent.listDeviceGroups()
- ctr, ret := 0, make([]*openflow_13.OfpGroupEntry, len(groups))
- for _, group := range groups {
- ret[ctr] = group
- ctr++
- }
- return &voltha.FlowGroups{Items: ret}, nil
-}
-
// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
// This function is called only in the Core that does not own this device. In the Core that owns this device then a
// deletion deletion also includes removal of any reference of this device.
@@ -350,21 +194,6 @@
}
}
-// RunPostDeviceDelete removes any reference of this device
-func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
- logger.Infow(ctx, "run-post-device-delete", log.Fields{"device-id": cDevice.Id})
- dMgr.stopManagingDevice(ctx, cDevice.Id)
- 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) {
- ctx = utils.WithRPCMetadataContext(ctx, "GetDevice")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- return dMgr.getDeviceReadOnly(ctx, id.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, "get-device-read-only", log.Fields{"device-id": id})
@@ -383,119 +212,12 @@
return agent.listDevicePorts(), nil
}
-// GetChildDevice will return a device, either from memory or from the dB, if present
-func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
- logger.Debugw(ctx, "get-child-device", log.Fields{"parent-device-id": parentDeviceID, "serialNumber": serialNumber,
- "parent-port-no": parentPortNo, "onu-id": onuID})
-
- parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
- if err != nil {
- return nil, status.Errorf(codes.Aborted, "%s", err.Error())
- }
- childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
- if len(childDeviceIds) == 0 {
- logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber, "onu-id": onuID})
- return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
- }
-
- var foundChildDevice *voltha.Device
- for childDeviceID := range childDeviceIds {
- var found bool
- if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
-
- foundOnuID := false
- if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
- if searchDevice.ParentPortNo == uint32(parentPortNo) {
- logger.Debugw(ctx, "found-child-by-onuid", log.Fields{"parent-device-id": parentDeviceID, "onu-id": onuID})
- foundOnuID = true
- }
- }
-
- foundSerialNumber := false
- if searchDevice.SerialNumber == serialNumber {
- logger.Debugw(ctx, "found-child-by-serial-number", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber})
- foundSerialNumber = true
- }
-
- // if both onuId and serialNumber are provided both must be true for the device to be found
- // otherwise whichever one found a match is good enough
- if onuID > 0 && serialNumber != "" {
- found = foundOnuID && foundSerialNumber
- } else {
- found = foundOnuID || foundSerialNumber
- }
-
- if found {
- foundChildDevice = searchDevice
- break
- }
- }
- }
-
- if foundChildDevice != nil {
- logger.Debugw(ctx, "child-device-found", log.Fields{"parent-device-id": parentDeviceID, "found-child-device": foundChildDevice})
- return foundChildDevice, nil
- }
-
- logger.Debugw(ctx, "child-device-not-found", log.Fields{"parent-device-id": parentDeviceID,
- "serial-number": serialNumber, "onu-id": onuID, "parent-port-no": parentPortNo})
- return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
-}
-
-// GetChildDeviceWithProxyAddress will return a device based on proxy address
-func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
- logger.Debugw(ctx, "get-child-device-with-proxy-address", log.Fields{"proxy-address": proxyAddress})
-
- parentDevicePorts, err := dMgr.listDevicePorts(ctx, proxyAddress.DeviceId)
- if err != nil {
- return nil, status.Errorf(codes.Aborted, "%s", err.Error())
- }
- childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
- if len(childDeviceIds) == 0 {
- logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": proxyAddress.DeviceId})
- return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
- }
-
- var foundChildDevice *voltha.Device
- for childDeviceID := range childDeviceIds {
- if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
- if searchDevice.ProxyAddress == proxyAddress {
- foundChildDevice = searchDevice
- break
- }
- }
- }
-
- if foundChildDevice != nil {
- logger.Debugw(ctx, "child-device-found", log.Fields{"proxy-address": proxyAddress})
- return foundChildDevice, nil
- }
-
- logger.Warnw(ctx, "child-device-not-found", log.Fields{"proxy-address": proxyAddress})
- return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
-}
-
// IsDeviceInCache returns true if device is found in the map
func (dMgr *Manager) IsDeviceInCache(id string) bool {
_, exist := dMgr.deviceAgents.Load(id)
return exist
}
-// ListDevices retrieves the latest devices from the data model
-func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ListDevices")
- logger.Debug(ctx, "list-devices")
- result := &voltha.Devices{}
-
- dMgr.deviceAgents.Range(func(key, value interface{}) bool {
- result.Items = append(result.Items, value.(*Agent).device)
- return true
- })
-
- logger.Debugw(ctx, "list-devices-end", log.Fields{"len": len(result.Items)})
- return result, nil
-}
-
//isParentDeviceExist checks whether device is already preprovisioned.
func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
hostPort := newDevice.GetHostAndPort()
@@ -547,7 +269,7 @@
// Proceed with the loading only if the device exist in the Model (could have been deleted)
if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
logger.Debugw(ctx, "loading-device", log.Fields{"device-id": deviceID})
- agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
+ agent := newAgent(device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout)
if _, err = agent.start(ctx, true, device); err != nil {
logger.Warnw(ctx, "failure-loading-device", log.Fields{"device-id": deviceID, "error": err})
} else {
@@ -648,132 +370,34 @@
return nil
}
-// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
-func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceIds")
- logger.Debug(ctx, "list-device-ids")
- // Report only device IDs that are in the device agent map
- return dMgr.listDeviceIdsFromMap(), nil
-}
-
-// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
-// trigger loading the devices along with their children and parent in memory
-func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ReconcileDevices")
-
- numDevices := 0
- if ids != nil {
- numDevices = len(ids.Items)
- }
-
- logger.Debugw(ctx, "reconcile-devices", log.Fields{"num-devices": numDevices})
- if ids != nil && len(ids.Items) != 0 {
- toReconcile := len(ids.Items)
- reconciled := 0
- var err error
- for _, id := range ids.Items {
- if err = dMgr.load(ctx, id.Id); err != nil {
- logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
- } else {
- reconciled++
- }
- }
- if toReconcile != reconciled {
- return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
- }
- } else {
- return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
- }
- return &empty.Empty{}, nil
-}
-
// adapterRestarted is invoked whenever an adapter is restarted
func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
logger.Debugw(ctx, "adapter-restarted", log.Fields{"adapter-id": adapter.Id, "vendor": adapter.Vendor,
- "current-replica": adapter.CurrentReplica, "total-replicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
+ "current-replica": adapter.CurrentReplica, "total-replicas": adapter.TotalReplicas, "restarted-endpoint": adapter.Endpoint})
- // Let's reconcile the device managed by this Core only
- if len(dMgr.rootDevices) == 0 {
- logger.Debugw(ctx, "nothing-to-reconcile", log.Fields{"adapter-id": adapter.Id})
- return nil
- }
-
- if len(dMgr.rootDevices) == 0 {
- logger.Debugw(ctx, "no-managed-device-to-reconcile", log.Fields{"adapter-id": adapter.Id})
- return nil
- }
-
- for rootDeviceID := range dMgr.rootDevices {
- dAgent := dMgr.getDeviceAgent(ctx, rootDeviceID)
- if dAgent == nil {
- continue
- }
- logger.Debugw(ctx, "checking-adapter-type", log.Fields{"agentType": dAgent.deviceType, "adapter-type": adapter.Type})
- if dAgent.deviceType == adapter.Type {
- rootDevice, _ := dAgent.getDeviceReadOnly(ctx)
- if rootDevice == nil {
- continue
- }
- isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, rootDeviceID, adapter.Type, adapter.CurrentReplica)
- if err != nil {
- logger.Warnw(ctx, "is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapter-type": adapter.Type, "replica-number": adapter.CurrentReplica})
- continue
- }
- if isDeviceOwnedByService {
- if rootDevice.AdminState != voltha.AdminState_PREPROVISIONED {
- logger.Debugw(ctx, "reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
- go dAgent.ReconcileDevice(ctx, rootDevice)
- } else {
- logger.Debugw(ctx, "not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
- }
- } else { // Should we be reconciling the root's children instead?
- rootDevicePorts, _ := dMgr.listDevicePorts(ctx, rootDeviceID)
- childManagedByAdapter:
- for _, port := range rootDevicePorts {
- for _, peer := range port.Peers {
- if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
- isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, childDevice.Id, adapter.Type, adapter.CurrentReplica)
- if err != nil {
- logger.Warnw(ctx, "is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapter-type": adapter.Type, "replica-number": adapter.CurrentReplica})
- }
- if isDeviceOwnedByService {
- if childDevice.AdminState != voltha.AdminState_PREPROVISIONED {
- logger.Debugw(ctx, "reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
- go dAgent.ReconcileDevice(ctx, childDevice)
- } else {
- logger.Debugw(ctx, "not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
- }
- } else {
- // All child devices under a parent device are typically managed by the same adapter type.
- // Therefore we only need to check whether the first device we retrieved is managed by that adapter
- break childManagedByAdapter
- }
- }
- }
- }
+ numberOfDevicesToReconcile := 0
+ dMgr.deviceAgents.Range(func(key, value interface{}) bool {
+ deviceAgent, ok := value.(*Agent)
+ if ok && deviceAgent.adapterEndpoint == adapter.Endpoint {
+ // Before reconciling, abort in-process request
+ if err := deviceAgent.abortAllProcessing(utils.WithNewSpanAndRPCMetadataContext(ctx, "AbortProcessingOnRestart")); err == nil {
+ logger.Debugw(ctx, "reconciling-device",
+ log.Fields{
+ "device-id": deviceAgent.deviceID,
+ "root-device": deviceAgent.isRootDevice,
+ "restarted-endpoint": adapter.Endpoint,
+ "device-type": deviceAgent.deviceType,
+ "adapter-type": adapter.Type,
+ })
+ go deviceAgent.ReconcileDevice(utils.WithNewSpanAndRPCMetadataContext(ctx, "ReconcileDevice"))
+ numberOfDevicesToReconcile++
+ } else {
+ logger.Errorw(ctx, "failed-aborting-exisiting-processing", log.Fields{"error": err})
}
}
- }
- logger.Debugw(ctx, "Reconciling for device on adapter restart is initiated", log.Fields{"adapter-id": adapter.Id})
-
- return nil
-}
-
-func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
- dAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
- if dAgent == nil {
- return status.Errorf(codes.NotFound, "error-unable to get agent from device")
- }
- if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
- for _, port := range parentDevicePorts {
- for _, peer := range port.Peers {
- if childDevice, err := dMgr.getDeviceFromModel(ctx, peer.DeviceId); err == nil {
- go dAgent.ReconcileDevice(ctx, childDevice)
- }
- }
- }
- logger.Debugw(ctx, "Reconcile initiated for child devices", log.Fields{"parent-device-id": parentDeviceID})
- }
+ return true
+ })
+ logger.Debugw(ctx, "reconciling-on-adapter-restart-initiated", log.Fields{"adapter-endpoint": adapter.Endpoint, "number-of-devices-to-reconcile": numberOfDevicesToReconcile})
return nil
}
@@ -831,6 +455,28 @@
return status.Errorf(codes.NotFound, "%s", deviceID)
}
+func (dMgr *Manager) canMultipleAdapterRequestProceed(ctx context.Context, deviceIDs []string) error {
+ ready := len(deviceIDs) > 0
+ for _, deviceID := range deviceIDs {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "adapter-nil", log.Fields{"device-id": deviceID})
+ return status.Errorf(codes.Unavailable, "adapter-nil-for-%s", deviceID)
+ }
+ ready = ready && agent.isAdapterConnectionUp(ctx)
+ if !ready {
+ return status.Errorf(codes.Unavailable, "adapter-connection-down-for-%s", deviceID)
+ }
+ if err := agent.canDeviceRequestProceed(ctx); err != nil {
+ return err
+ }
+ }
+ if !ready {
+ return status.Error(codes.Unavailable, "adapter(s)-not-ready")
+ }
+ return nil
+}
+
func (dMgr *Manager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
logger.Debugw(ctx, "add-flows-and-groups", log.Fields{"device-id": deviceID, "groups:": groups, "flow-metadata": flowMetadata})
if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
@@ -867,21 +513,6 @@
return status.Errorf(codes.NotFound, "%s", deviceID)
}
-// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
-// following a user action
-func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "UpdateDevicePmConfigs")
- log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
- if configs.Id == "" {
- return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
- }
- agent := dMgr.getDeviceAgent(ctx, configs.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
- }
- return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
-}
-
// InitPmConfigs initialize the pm configs as defined by the adapter.
func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
if pmConfigs.Id == "" {
@@ -893,17 +524,6 @@
return status.Errorf(codes.NotFound, "%s", deviceID)
}
-// ListDevicePmConfigs returns pm configs of device
-func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePmConfigs")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", id.Id)
- }
- return agent.listPmConfigs(ctx)
-}
-
func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
logger.Debugw(ctx, "get-switch-capability", log.Fields{"device-id": deviceID})
if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
@@ -912,15 +532,6 @@
return nil, status.Errorf(codes.NotFound, "%s", deviceID)
}
-func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
- logger.Debugw(ctx, "get-ports", log.Fields{"device-id": deviceID, "port-type": portType})
- agent := dMgr.getDeviceAgent(ctx, deviceID)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", deviceID)
- }
- return agent.getPorts(ctx, portType), nil
-}
-
func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
logger.Debugw(ctx, "update-device-status", log.Fields{"device-id": deviceID, "oper-status": operStatus, "conn-status": connStatus})
if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
@@ -974,31 +585,6 @@
return status.Errorf(codes.NotFound, "%s", deviceID)
}
-func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
- logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": deviceID})
- if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
- if err := agent.deleteAllPorts(ctx); err != nil {
- return err
- }
- // 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.getDeviceReadOnly(ctx, deviceID); err == nil {
- go func() {
- subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
- if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(subCtx, device); err != nil {
- logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
- }
- }()
- } else {
- logger.Warnw(ctx, "failed-to-retrieve-device", log.Fields{"device-id": deviceID})
- return err
- }
- return nil
- }
- return status.Errorf(codes.NotFound, "%s", deviceID)
-}
-
//UpdatePortsState updates all ports on the device
func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, portTypeFilter uint32, state voltha.OperStatus_Types) error {
logger.Debugw(ctx, "update-ports-state", log.Fields{"device-id": deviceID})
@@ -1016,80 +602,6 @@
return nil
}
-func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
- channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
- logger.Debugw(ctx, "child-device-detected", log.Fields{"parent-device-id": parentDeviceID, "parent-port-no": parentPortNo, "device-type": deviceType, "channel-id": channelID, "vendor-id": vendorID, "serial-number": serialNumber, "onu-id": onuID})
-
- if deviceType == "" && vendorID != "" {
- logger.Debug(ctx, "device-type-is-nil-fetching-device-type")
- deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
- if err != nil {
- return nil, err
- }
- OLoop:
- for _, dType := range deviceTypes.Items {
- for _, v := range dType.VendorIds {
- if v == vendorID {
- deviceType = dType.Adapter
- break OLoop
- }
- }
- }
- }
- //if no match found for the vendorid,report adapter with the custom error message
- if deviceType == "" {
- logger.Errorw(ctx, "failed-to-fetch-adapter-name ", log.Fields{"vendor-id": vendorID})
- return nil, status.Errorf(codes.NotFound, "%s", vendorID)
- }
-
- // Create the ONU device
- childDevice := &voltha.Device{}
- childDevice.Type = deviceType
- childDevice.ParentId = parentDeviceID
- childDevice.ParentPortNo = uint32(parentPortNo)
- childDevice.VendorId = vendorID
- childDevice.SerialNumber = serialNumber
- childDevice.Root = false
-
- // Get parent device type
- pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
- if pAgent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
- }
- if pAgent.deviceType == "" {
- return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
- }
-
- if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
- logger.Warnw(ctx, "child-device-exists", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber})
- return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
- }
-
- childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
-
- // Create and start a device agent for that device
- agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
- insertedChildDevice, err := agent.start(ctx, false, childDevice)
- if err != nil {
- logger.Errorw(ctx, "error-starting-child-device", log.Fields{"parent-device-id": childDevice.ParentId, "child-device-id": agent.deviceID, "error": err})
- return nil, err
- }
- dMgr.addDeviceAgentToMap(agent)
-
- // Activate the child device
- if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
- go func() {
- subCtx := utils.WithFromTopicMetadataFromContext(utils.WithSpanAndRPCMetadataFromContext(ctx), ctx)
- err := agent.enableDevice(subCtx)
- if err != nil {
- logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
- }
- }()
- }
-
- return insertedChildDevice, nil
-}
-
func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
logger.Debugw(ctx, "packet-out", log.Fields{"device-id": deviceID, "out-port": outPort})
if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
@@ -1113,7 +625,7 @@
return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
}
- if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
+ if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, packet); err != nil {
return err
}
return nil
@@ -1127,47 +639,6 @@
return status.Errorf(codes.NotFound, "%s", device.Id)
}
-//
-//CreateLogicalDevice creates logical device in core
-func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
- logger.Info(ctx, "create-logical-device")
- // Verify whether the logical device has already been created
- if cDevice.ParentId != "" {
- logger.Debugw(ctx, "parent-device-already-exist", log.Fields{"device-id": cDevice.Id, "logical-device-id": cDevice.Id})
- return nil
- }
- var err error
- if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
- logger.Warnw(ctx, "create-logical-device-error", log.Fields{"device": cDevice})
- return err
- }
- return nil
-}
-
-// DeleteLogicalDevice deletes logical device from core
-func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
- logger.Info(ctx, "delete-logical-device")
- var err error
- if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
- logger.Warnw(ctx, "delete-logical-device-error", log.Fields{"device-id": cDevice.Id})
- return err
- }
- // Remove the logical device Id from the parent device
- logicalID := ""
- dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
- return nil
-}
-
-// DeleteLogicalPorts removes the logical ports associated with that deviceId
-func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
- logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
- if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
- // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
- logger.Warnw(ctx, "delete-logical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
- }
- return nil
-}
-
func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
// Sanity check
if childDevice.Root {
@@ -1178,54 +649,6 @@
return parentDevice
}
-//ChildDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
-//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, "child-devices-lost")
- parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentDeviceID)
- if err != nil {
- logger.Warnw(ctx, "failed-getting-device", log.Fields{"parent-device-id": parentDeviceID, "error": err})
- return err
- }
- return dMgr.DisableAllChildDevices(ctx, parentDevice)
-}
-
-//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
-// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
-func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
- logger.Debug(ctx, "child-devices-detected")
- parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
- if err != nil {
- logger.Warnw(ctx, "failed-getting-device", log.Fields{"device-id": parentDeviceID, "error": err})
- return err
- }
- childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
- if len(childDeviceIds) == 0 {
- logger.Debugw(ctx, "no-child-device", log.Fields{"parent-device-id": parentDeviceID})
- }
- allChildEnableRequestSent := true
- for childDeviceID := range childDeviceIds {
- if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
- subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
- // Run the children re-registration in its own routine
- go func(ctx context.Context) {
- err = agent.enableDevice(ctx)
- if err != nil {
- logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
- }
- }(subCtx)
- } else {
- err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
- logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parent-device-id": parentDeviceID, "child-id": childDeviceID})
- allChildEnableRequestSent = false
- }
- }
- if !allChildEnableRequestSent {
- return err
- }
- return nil
-}
-
/*
All the functions below are callback functions where they are invoked with the latest and previous data. We can
therefore use the data as is without trying to get the latest from the model.
@@ -1246,63 +669,6 @@
return nil
}
-//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
-func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
- logger.Debug(ctx, "delete-all-child-devices")
- force := false
- // Get the parent device Transient state, if its FORCE_DELETED(go for force delete for child devices)
- // So in cases when this handler is getting called other than DELETE operation, no force option would be used.
- agent := dMgr.getDeviceAgent(ctx, parentCurrDevice.Id)
- if agent == nil {
- return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
- }
-
- force = agent.getTransientState() == voltha.DeviceTransientState_FORCE_DELETING
-
- ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
- for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
- if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
- if force {
- if err := agent.deleteDeviceForce(ctx); err != nil {
- logger.Warnw(ctx, "failure-delete-device-force", log.Fields{"device-id": childDeviceID,
- "error": err.Error()})
- }
- } else {
- if err := agent.deleteDevice(ctx); err != nil {
- logger.Warnw(ctx, "failure-delete-device", log.Fields{"device-id": childDeviceID,
- "error": err.Error()})
- }
- }
- // No further action is required here. The deleteDevice will change the device state where the resulting
- // callback will take care of cleaning the child device agent.
- }
- }
- return nil
-}
-
-//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
-func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
- logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
- if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
- // Just log error as logical device may already have been deleted
- logger.Warnw(ctx, "delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
- }
- return nil
-}
-
-//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
-func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
- logger.Debugw(ctx, "delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
- if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
- if err := agent.deleteAllFlows(ctx); err != nil {
- logger.Errorw(ctx, "error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
- return err
- }
- return nil
- }
- return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
-}
-
//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
func (dMgr *Manager) getAllChildDeviceIds(ctx context.Context, parentDevicePorts map[uint32]*voltha.Port) map[string]struct{} {
logger.Debug(ctx, "get-all-child-device-ids")
@@ -1316,8 +682,8 @@
return childDeviceIds
}
-//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
-func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
+//GgtAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
+func (dMgr *Manager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
logger.Debugw(ctx, "get-all-child-devices", log.Fields{"parent-device-id": parentDeviceID})
if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
childDevices := make([]*voltha.Device, 0)
@@ -1331,165 +697,6 @@
return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
}
-// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
-func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
- logger.Info(ctx, "setup-uni-logical-ports")
- cDevicePorts, err := dMgr.listDevicePorts(ctx, cDevice.Id)
- if err != nil {
- return err
- }
- if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice, cDevicePorts); err != nil {
- logger.Warnw(ctx, "setup-uni-logical-ports-error", log.Fields{"device": cDevice, "err": err})
- return err
- }
- return nil
-}
-
-// convenience to avoid redefining
-var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
-
-// DownloadImage execute an image download request
-func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "DownloadImage")
- log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
- logger.Debugw(ctx, "download-image", log.Fields{"device-id": img.Id, "image-name": img.Name})
- agent := dMgr.getDeviceAgent(ctx, img.Id)
- if agent == nil {
- return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
- }
- resp, err := agent.downloadImage(ctx, img)
- if err != nil {
- return operationFailureResp, err
- }
- return resp, nil
-}
-
-// CancelImageDownload cancels image download request
-func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "CancelImageDownload")
- log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
- logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
- agent := dMgr.getDeviceAgent(ctx, img.Id)
- if agent == nil {
- return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
- }
- resp, err := agent.cancelImageDownload(ctx, img)
- if err != nil {
- return operationFailureResp, err
- }
- return resp, nil
-}
-
-// ActivateImageUpdate activates image update request
-func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ActivateImageUpdate")
- log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
- logger.Debugw(ctx, "activate-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
- agent := dMgr.getDeviceAgent(ctx, img.Id)
- if agent == nil {
- return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
- }
- resp, err := agent.activateImage(ctx, img)
- if err != nil {
- return operationFailureResp, err
- }
- return resp, nil
-}
-
-// RevertImageUpdate reverts image update
-func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "RevertImageUpdate")
- log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
- logger.Debugw(ctx, "rever-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
- agent := dMgr.getDeviceAgent(ctx, img.Id)
- if agent == nil {
- return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
- }
- resp, err := agent.revertImage(ctx, img)
- if err != nil {
- return operationFailureResp, err
- }
- return resp, nil
-}
-
-// convenience to avoid redefining
-var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
-
-// GetImageDownloadStatus returns status of image download
-func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownloadStatus")
- log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
- logger.Debugw(ctx, "get-image-download-status", log.Fields{"device-id": img.Id, "image-name": img.Name})
- agent := dMgr.getDeviceAgent(ctx, img.Id)
- if agent == nil {
- return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
- }
- resp, err := agent.getImageDownloadStatus(ctx, img)
- if err != nil {
- return imageDownloadFailureResp, err
- }
- return resp, nil
-}
-
-func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
- ctx = utils.WithRPCMetadataContext(ctx, "UpdateImageDownload")
- log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
- logger.Debugw(ctx, "update-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
- if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
- if err := agent.updateImageDownload(ctx, img); err != nil {
- logger.Debugw(ctx, "update-image-download-failed", log.Fields{"err": err, "image-name": img.Name})
- return err
- }
- } else {
- return status.Errorf(codes.NotFound, "%s", img.Id)
- }
- return nil
-}
-
-// GetImageDownload returns image download
-func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownload")
- log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
- logger.Debugw(ctx, "get-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
- agent := dMgr.getDeviceAgent(ctx, img.Id)
- if agent == nil {
- return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
- }
- resp, err := agent.getImageDownload(ctx, img)
- if err != nil {
- return imageDownloadFailureResp, err
- }
- return resp, nil
-}
-
-// ListImageDownloads returns image downloads
-func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "ListImageDownloads")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "list-image-downloads", log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
- }
- resp, err := agent.listImageDownloads(ctx, id.Id)
- if err != nil {
- return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
- }
- return resp, nil
-}
-
-// GetImages returns all images for a specific device entry
-func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "GetImages")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- logger.Debugw(ctx, "get-images", log.Fields{"device-id": id.Id})
- device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
- if err != nil {
- return nil, err
- }
- return device.Images, nil
-}
-
func (dMgr *Manager) NotifyInvalidTransition(ctx context.Context, device *voltha.Device) error {
logger.Errorw(ctx, "notify-invalid-transition", log.Fields{
"device": device.Id,
@@ -1517,21 +724,6 @@
return ""
}
-func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "SimulateAlarm")
- logger.Debugw(ctx, "simulate-alarm", log.Fields{"id": simulateReq.Id, "indicator": simulateReq.Indicator, "intf-id": simulateReq.IntfId,
- "port-type-name": simulateReq.PortTypeName, "onu-device-id": simulateReq.OnuDeviceId, "inverse-bit-error-rate": simulateReq.InverseBitErrorRate,
- "drift": simulateReq.Drift, "new-eqd": simulateReq.NewEqd, "onu-serial-number": simulateReq.OnuSerialNumber, "operation": simulateReq.Operation})
- agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
- }
- if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
- return nil, err
- }
- return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
-}
-
func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
logger.Debugw(ctx, "update-device-reason", log.Fields{"device-id": deviceID, "reason": reason})
if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
@@ -1540,368 +732,20 @@
return status.Errorf(codes.NotFound, "%s", deviceID)
}
-func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "EnablePort")
- log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
- logger.Debugw(ctx, "enable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
- agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
- }
- return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
-}
-
-func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "DisablePort")
- log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
- logger.Debugw(ctx, "disable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
- agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
- }
- return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
-}
-
-// ChildDeviceLost calls parent adapter to delete child device and all its references
-func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
- logger.Debugw(ctx, "child-device-lost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
- if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
- if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
- // Just log the message and let the remaining pipeline proceed.
- logger.Warnw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
- }
- }
- // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
- return nil
-}
-
-func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "StartOmciTestAction")
- log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
- logger.Debugw(ctx, "start-omci-test-action", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
- agent := dMgr.getDeviceAgent(ctx, request.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", request.Id)
- }
- return agent.startOmciTest(ctx, request)
-}
-
-func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "GetExtValue")
- log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
- logger.Debugw(ctx, "get-ext-value", log.Fields{"onu-id": value.Id})
- cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
- if err != nil {
- return nil, status.Errorf(codes.Aborted, "%s", err.Error())
- }
- pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
- if err != nil {
- return nil, status.Errorf(codes.Aborted, "%s", err.Error())
- }
- if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
- resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
- if err != nil {
- return nil, err
- }
- logger.Debugw(ctx, "get-ext-value-result", log.Fields{"result": resp})
- return resp, nil
- }
- return nil, status.Errorf(codes.NotFound, "%s", value.Id)
-
-}
-
-// SetExtValue set some given configs or value
-func (dMgr *Manager) SetExtValue(ctx context.Context, value *voltha.ValueSet) (*empty.Empty, error) {
- ctx = utils.WithRPCMetadataContext(ctx, "SetExtValue")
- logger.Debugw(ctx, "set-ext-value", log.Fields{"onu-id": value.Id})
- device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
- if err != nil {
- return nil, status.Errorf(codes.Aborted, "%s", err.Error())
- }
- if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
- resp, err := agent.setExtValue(ctx, device, value)
- if err != nil {
- return nil, err
- }
- logger.Debugw(ctx, "set-ext-value-result", log.Fields{"result": resp})
- return resp, nil
- }
- return nil, status.Errorf(codes.NotFound, "%s", value.Id)
-
-}
-
func (dMgr *Manager) SendRPCEvent(ctx context.Context, id string, rpcEvent *voltha.RPCEvent,
category voltha.EventCategory_Types, subCategory *voltha.EventSubCategory_Types, raisedTs int64) {
//TODO Instead of directly sending to the kafka bus, queue the message and send it asynchronously
dMgr.Agent.SendRPCEvent(ctx, id, rpcEvent, category, subCategory, raisedTs)
}
-func (dMgr *Manager) GetTransientState(ctx context.Context, id string) (voltha.DeviceTransientState_Types, error) {
+func (dMgr *Manager) GetTransientState(ctx context.Context, id string) (core.DeviceTransientState_Types, error) {
agent := dMgr.getDeviceAgent(ctx, id)
if agent == nil {
- return voltha.DeviceTransientState_NONE, status.Errorf(codes.NotFound, "%s", id)
+ return core.DeviceTransientState_NONE, status.Errorf(codes.NotFound, "%s", id)
}
return agent.getTransientState(), nil
}
-func (dMgr *Manager) DownloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
- if err := dMgr.validateImageDownloadRequest(request); err != nil {
- return nil, err
- }
-
- ctx = utils.WithRPCMetadataContext(ctx, "DownloadImageToDevice")
- respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
-
- for index, deviceID := range request.DeviceId {
- // Create download request per device
- downloadReq := &voltha.DeviceImageDownloadRequest{
- Image: request.Image,
- ActivateOnSuccess: request.ActivateOnSuccess,
- CommitOnSuccess: request.CommitOnSuccess,
- }
-
- //slice-out only single deviceID from the request
- downloadReq.DeviceId = request.DeviceId[index : index+1]
-
- go func(deviceID string, req *voltha.DeviceImageDownloadRequest, ch chan []*voltha.DeviceImageState) {
- agent := dMgr.getDeviceAgent(ctx, deviceID)
- if agent == nil {
- logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
- ch <- nil
- return
- }
-
- resp, err := agent.downloadImageToDevice(ctx, req)
- if err != nil {
- logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
-
- err = dMgr.validateDeviceImageResponse(resp)
- if err != nil {
- logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
- ch <- resp.GetDeviceImageStates()
- }(deviceID.GetId(), downloadReq, respCh)
-
- }
-
- return dMgr.waitForAllResponses(ctx, "download-image-to-device", respCh, len(request.GetDeviceId()))
-}
-
-func (dMgr *Manager) GetImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
- if err := dMgr.validateImageRequest(request); err != nil {
- return nil, err
- }
-
- ctx = utils.WithRPCMetadataContext(ctx, "GetImageStatus")
-
- respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
- for index, deviceID := range request.DeviceId {
- // Create status request per device
- imageStatusReq := &voltha.DeviceImageRequest{
- Version: request.Version,
- CommitOnSuccess: request.CommitOnSuccess,
- }
-
- //slice-out only single deviceID from the request
- imageStatusReq.DeviceId = request.DeviceId[index : index+1]
-
- go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
- agent := dMgr.getDeviceAgent(ctx, deviceID)
- if agent == nil {
- logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
- ch <- nil
- return
- }
-
- resp, err := agent.getImageStatus(ctx, req)
- if err != nil {
- logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
-
- err = dMgr.validateDeviceImageResponse(resp)
- if err != nil {
- logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
- ch <- resp.GetDeviceImageStates()
- }(deviceID.GetId(), imageStatusReq, respCh)
-
- }
-
- return dMgr.waitForAllResponses(ctx, "get-image-status", respCh, len(request.GetDeviceId()))
-}
-
-func (dMgr *Manager) AbortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
- if err := dMgr.validateImageRequest(request); err != nil {
- return nil, err
- }
-
- ctx = utils.WithRPCMetadataContext(ctx, "AbortImageUpgradeToDevice")
- respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
-
- for index, deviceID := range request.DeviceId {
- // Create abort request per device
- abortImageReq := &voltha.DeviceImageRequest{
- Version: request.Version,
- CommitOnSuccess: request.CommitOnSuccess,
- }
-
- //slice-out only single deviceID from the request
- abortImageReq.DeviceId = request.DeviceId[index : index+1]
-
- go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
- agent := dMgr.getDeviceAgent(ctx, deviceID)
- if agent == nil {
- logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
- ch <- nil
- return
- }
-
- resp, err := agent.abortImageUpgradeToDevice(ctx, req)
- if err != nil {
- logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
-
- err = dMgr.validateDeviceImageResponse(resp)
- if err != nil {
- logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
- ch <- resp.GetDeviceImageStates()
- }(deviceID.GetId(), abortImageReq, respCh)
-
- }
-
- return dMgr.waitForAllResponses(ctx, "abort-image-upgrade-to-device", respCh, len(request.GetDeviceId()))
-}
-
-func (dMgr *Manager) GetOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
- if id == nil || id.Id == "" {
- return nil, status.Errorf(codes.InvalidArgument, "empty device id")
- }
-
- ctx = utils.WithRPCMetadataContext(ctx, "GetOnuImages")
- log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
- agent := dMgr.getDeviceAgent(ctx, id.Id)
- if agent == nil {
- return nil, status.Errorf(codes.NotFound, "%s", id.Id)
- }
-
- resp, err := agent.getOnuImages(ctx, id)
- if err != nil {
- return nil, err
- }
-
- logger.Debugw(ctx, "get-onu-images-result", log.Fields{"onu-image": resp.Items})
-
- return resp, nil
-}
-
-func (dMgr *Manager) ActivateImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
- if err := dMgr.validateImageRequest(request); err != nil {
- return nil, err
- }
-
- ctx = utils.WithRPCMetadataContext(ctx, "ActivateImage")
- respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
-
- for index, deviceID := range request.DeviceId {
- // Create activate request per device
- activateImageReq := &voltha.DeviceImageRequest{
- Version: request.Version,
- CommitOnSuccess: request.CommitOnSuccess,
- }
-
- //slice-out only single deviceID from the request
- activateImageReq.DeviceId = request.DeviceId[index : index+1]
-
- go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
- agent := dMgr.getDeviceAgent(ctx, deviceID)
- if agent == nil {
- logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
- ch <- nil
- return
- }
-
- resp, err := agent.activateImageOnDevice(ctx, req)
- if err != nil {
- logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
-
- err = dMgr.validateDeviceImageResponse(resp)
- if err != nil {
- logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
-
- ch <- resp.GetDeviceImageStates()
- }(deviceID.GetId(), activateImageReq, respCh)
-
- }
-
- return dMgr.waitForAllResponses(ctx, "activate-image", respCh, len(request.GetDeviceId()))
-}
-
-func (dMgr *Manager) CommitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
- if err := dMgr.validateImageRequest(request); err != nil {
- return nil, err
- }
-
- ctx = utils.WithRPCMetadataContext(ctx, "CommitImage")
- respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
-
- for index, deviceID := range request.DeviceId {
- // Create commit request per device
- commitImageReq := &voltha.DeviceImageRequest{
- Version: request.Version,
- CommitOnSuccess: request.CommitOnSuccess,
- }
- //slice-out only single deviceID from the request
- commitImageReq.DeviceId = request.DeviceId[index : index+1]
-
- go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
- agent := dMgr.getDeviceAgent(ctx, deviceID)
- if agent == nil {
- logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
- ch <- nil
- return
- }
-
- resp, err := agent.commitImage(ctx, req)
- if err != nil {
- logger.Errorw(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
-
- err = dMgr.validateDeviceImageResponse(resp)
- if err != nil {
- logger.Errorf(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
- ch <- nil
- return
- }
- ch <- resp.GetDeviceImageStates()
- }(deviceID.GetId(), commitImageReq, respCh)
-
- }
-
- return dMgr.waitForAllResponses(ctx, "commit-image", respCh, len(request.GetDeviceId()))
-}
-
func (dMgr *Manager) validateImageDownloadRequest(request *voltha.DeviceImageDownloadRequest) error {
if request == nil || request.Image == nil || len(request.DeviceId) == 0 {
return status.Errorf(codes.InvalidArgument, "invalid argument")
@@ -1979,3 +823,12 @@
}
return nil
}
+
+func (dMgr *Manager) adapterRestartedHandler(ctx context.Context, endpoint string) error {
+ // Get the adapter corresponding to that endpoint
+ if a, _ := dMgr.adapterMgr.GetAdapterWithEndpoint(ctx, endpoint); a != nil {
+ return dMgr.adapterRestarted(ctx, a)
+ }
+ logger.Errorw(ctx, "restarted-adapter-not-found", log.Fields{"endpoint": endpoint})
+ return fmt.Errorf("restarted adapter at endpoint %s not found", endpoint)
+}
diff --git a/rw_core/core/device/manager_nbi.go b/rw_core/core/device/manager_nbi.go
new file mode 100644
index 0000000..9a16812
--- /dev/null
+++ b/rw_core/core/device/manager_nbi.go
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package device
+
+import (
+ "context"
+ "errors"
+
+ "github.com/golang/protobuf/ptypes/empty"
+ "github.com/opencord/voltha-go/rw_core/utils"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+// CreateDevice creates a new parent device in the data model
+func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
+ if device.MacAddress == "" && device.GetHostAndPort() == "" {
+ logger.Errorf(ctx, "no-device-info-present")
+ return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
+ }
+ ctx = utils.WithRPCMetadataContext(ctx, "CreateDevice")
+ logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
+
+ deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
+ if err != nil {
+ logger.Errorf(ctx, "failed-to-fetch-parent-device-info")
+ return nil, err
+ }
+ if deviceExist {
+ logger.Errorf(ctx, "device-is-pre-provisioned-already-with-same-ip-port-or-mac-address")
+ return nil, errors.New("device is already pre-provisioned")
+ }
+ logger.Debugw(ctx, "create-device", log.Fields{"device": device})
+
+ // Ensure this device is set as root
+ device.Root = true
+ // Create and start a device agent for that device
+ agent := newAgent(device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout)
+ device, err = agent.start(ctx, false, device)
+ if err != nil {
+ logger.Errorw(ctx, "fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
+ return nil, err
+ }
+ dMgr.addDeviceAgentToMap(agent)
+ return device, nil
+}
+
+// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
+func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "EnableDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "enable-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.enableDevice(ctx)
+}
+
+// DisableDevice disables a device along with any child device it may have
+func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DisableDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "disable-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.disableDevice(ctx)
+}
+
+//RebootDevice invoked the reboot API to the corresponding adapter
+func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "RebootDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.rebootDevice(ctx)
+}
+
+// DeleteDevice removes a device from the data model
+func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DeleteDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "delete-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.deleteDevice(ctx)
+}
+
+// ForceDeleteDevice removes a device from the data model forcefully without successfully waiting for the adapters.
+func (dMgr *Manager) ForceDeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ForceDeleteDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "force-delete-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.deleteDeviceForce(ctx)
+}
+
+// ListDevices retrieves the latest devices from the data model
+func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDevices")
+
+ logger.Debug(ctx, "list-devices")
+ result := &voltha.Devices{}
+
+ dMgr.deviceAgents.Range(func(key, value interface{}) bool {
+ result.Items = append(result.Items, value.(*Agent).device)
+ return true
+ })
+
+ logger.Debugw(ctx, "list-devices-end", log.Fields{"len": len(result.Items)})
+ return result, nil
+}
+
+// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
+func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceIds")
+
+ logger.Debug(ctx, "list-device-ids")
+ // Report only device IDs that are in the device agent map
+ return dMgr.listDeviceIdsFromMap(), nil
+}
+
+// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
+// trigger loading the devices along with their children and parent in memory
+func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ReconcileDevices")
+
+ numDevices := 0
+ if ids != nil {
+ numDevices = len(ids.Items)
+ }
+
+ logger.Debugw(ctx, "reconcile-devices", log.Fields{"num-devices": numDevices})
+ if ids != nil && len(ids.Items) != 0 {
+ toReconcile := len(ids.Items)
+ reconciled := 0
+ var err error
+ for _, id := range ids.Items {
+ if err = dMgr.load(ctx, id.Id); err != nil {
+ logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
+ } else {
+ reconciled++
+ }
+ }
+ if toReconcile != reconciled {
+ return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
+ }
+ } else {
+ return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
+ }
+ return &empty.Empty{}, 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) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ return dMgr.getDeviceReadOnly(ctx, id.Id)
+}
+
+// convenience to avoid redefining
+var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
+
+// DownloadImage execute an image download request
+func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DownloadImage")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "download-image", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.downloadImage(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+// CancelImageDownload cancels image download request
+func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "CancelImageDownload")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.cancelImageDownload(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+// ActivateImageUpdate activates image update request
+func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ActivateImageUpdate")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "activate-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.activateImage(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+// RevertImageUpdate reverts image update
+func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "RevertImageUpdate")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "rever-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.revertImage(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+func (dMgr *Manager) DownloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageDownloadRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "DownloadImageToDevice")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create download request per device
+ downloadReq := &voltha.DeviceImageDownloadRequest{
+ Image: request.Image,
+ ActivateOnSuccess: request.ActivateOnSuccess,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ downloadReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageDownloadRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.downloadImageToDevice(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), downloadReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "download-image-to-device", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) GetImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImageStatus")
+
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+ for index, deviceID := range request.DeviceId {
+ // Create status request per device
+ imageStatusReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ imageStatusReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.getImageStatus(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), imageStatusReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "get-image-status", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) AbortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "AbortImageUpgradeToDevice")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create abort request per device
+ abortImageReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ abortImageReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.abortImageUpgradeToDevice(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), abortImageReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "abort-image-upgrade-to-device", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) GetOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
+ if id == nil || id.Id == "" {
+ return nil, status.Errorf(codes.InvalidArgument, "empty device id")
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "GetOnuImages")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+
+ resp, err := agent.getOnuImages(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+
+ logger.Debugw(ctx, "get-onu-images-result", log.Fields{"onu-image": resp.Items})
+
+ return resp, nil
+}
+
+func (dMgr *Manager) ActivateImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "ActivateImage")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create activate request per device
+ activateImageReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ activateImageReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.activateImageOnDevice(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), activateImageReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "activate-image", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) CommitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "CommitImage")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create commit request per device
+ commitImageReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+ //slice-out only single deviceID from the request
+ commitImageReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.commitImage(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorf(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), commitImageReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "commit-image", respCh, len(request.GetDeviceId()))
+}
+
+// convenience to avoid redefining
+var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
+
+// GetImageDownloadStatus returns status of image download
+func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownloadStatus")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "get-image-download-status", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.getImageDownloadStatus(ctx, img)
+ if err != nil {
+ return imageDownloadFailureResp, err
+ }
+ return resp, nil
+}
+
+// GetImageDownload returns image download
+func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownload")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "get-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.getImageDownload(ctx, img)
+ if err != nil {
+ return imageDownloadFailureResp, err
+ }
+ return resp, nil
+}
+
+// ListImageDownloads returns image downloads
+func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListImageDownloads")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "list-image-downloads", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ resp, err := agent.listImageDownloads(ctx, id.Id)
+ if err != nil {
+ return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
+ }
+ return resp, nil
+}
+
+// GetImages returns all images for a specific device entry
+func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImages")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "get-images", log.Fields{"device-id": id.Id})
+ device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
+ if err != nil {
+ return nil, err
+ }
+ return device.Images, nil
+}
+
+// ListDevicePorts returns the ports details for a specific device entry
+func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePorts")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
+ }
+
+ ports := agent.listDevicePorts()
+ ctr, ret := 0, make([]*voltha.Port, len(ports))
+ for _, port := range ports {
+ ret[ctr] = port
+ ctr++
+ }
+ return &voltha.Ports{Items: ret}, nil
+}
+
+// ListDevicePmConfigs returns pm configs of device
+func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePmConfigs")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return agent.listPmConfigs(ctx)
+}
+
+// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
+// following a user action
+func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "UpdateDevicePmConfigs")
+ log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
+
+ if configs.Id == "" {
+ return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
+ }
+ agent := dMgr.getDeviceAgent(ctx, configs.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
+ }
+ return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
+}
+
+// ListDeviceFlows returns the flow details for a specific device entry
+func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlows")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+ logger.Debugw(ctx, "list-device-flows", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
+ }
+
+ flows := agent.listDeviceFlows()
+ ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
+ for _, flow := range flows {
+ ret[ctr] = flow
+ ctr++
+ }
+ return &ofp.Flows{Items: ret}, nil
+}
+
+// ListDeviceFlowGroups returns the flow group details for a specific device entry
+func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlowGroups")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+ logger.Debugw(ctx, "list-device-flow-groups", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
+ }
+ groups := agent.listDeviceGroups()
+ ctr, ret := 0, make([]*ofp.OfpGroupEntry, len(groups))
+ for _, group := range groups {
+ ret[ctr] = group
+ ctr++
+ }
+ return &voltha.FlowGroups{Items: ret}, nil
+}
+
+func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "EnablePort")
+ log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
+
+ logger.Debugw(ctx, "enable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
+ agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
+ }
+ return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
+}
+
+func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DisablePort")
+ log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
+
+ logger.Debugw(ctx, "disable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
+ agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
+ }
+ return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
+}
+
+func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetExtValue")
+ log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
+
+ logger.Debugw(ctx, "get-ext-value", log.Fields{"onu-id": value.Id})
+ cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
+ resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
+ if err != nil {
+ return nil, err
+ }
+ logger.Debugw(ctx, "get-ext-value-result", log.Fields{"result": resp})
+ return resp, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", value.Id)
+
+}
+
+// SetExtValue set some given configs or value
+func (dMgr *Manager) SetExtValue(ctx context.Context, value *voltha.ValueSet) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "SetExtValue")
+ logger.Debugw(ctx, "set-ext-value", log.Fields{"onu-id": value.Id})
+
+ device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
+ resp, err := agent.setExtValue(ctx, device, value)
+ if err != nil {
+ return nil, err
+ }
+ logger.Debugw(ctx, "set-ext-value-result", log.Fields{"result": resp})
+ return resp, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", value.Id)
+
+}
+
+func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "StartOmciTestAction")
+ log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
+
+ logger.Debugw(ctx, "start-omci-test-action", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
+ agent := dMgr.getDeviceAgent(ctx, request.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", request.Id)
+ }
+ return agent.startOmciTest(ctx, request)
+}
+
+func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "SimulateAlarm")
+
+ logger.Debugw(ctx, "simulate-alarm", log.Fields{"id": simulateReq.Id, "indicator": simulateReq.Indicator, "intf-id": simulateReq.IntfId,
+ "port-type-name": simulateReq.PortTypeName, "onu-device-id": simulateReq.OnuDeviceId, "inverse-bit-error-rate": simulateReq.InverseBitErrorRate,
+ "drift": simulateReq.Drift, "new-eqd": simulateReq.NewEqd, "onu-serial-number": simulateReq.OnuSerialNumber, "operation": simulateReq.Operation})
+ agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
+ }
+ if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
+ return nil, err
+ }
+ return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
+}
diff --git a/rw_core/core/device/manager_sbi.go b/rw_core/core/device/manager_sbi.go
new file mode 100644
index 0000000..53d2a24
--- /dev/null
+++ b/rw_core/core/device/manager_sbi.go
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package device
+
+import (
+ "context"
+
+ "github.com/golang/protobuf/ptypes/empty"
+ "github.com/opencord/voltha-go/rw_core/utils"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+func (dMgr *Manager) PortCreated(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "PortCreated")
+
+ logger.Debugw(ctx, "port-created", log.Fields{"port": port})
+
+ agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
+ if agent != nil {
+ if err := agent.addPort(ctx, port); err != nil {
+ return nil, err
+ }
+ // Setup peer ports in its own routine
+ go func() {
+ if err := dMgr.addPeerPort(log.WithSpanFromContext(context.Background(), ctx), port.DeviceId, port); err != nil {
+ logger.Errorw(ctx, "unable-to-add-peer-port", log.Fields{"error": err, "device-id": port.DeviceId})
+ }
+ }()
+ return &empty.Empty{}, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
+}
+
+func (dMgr *Manager) DeviceUpdate(ctx context.Context, device *voltha.Device) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeviceUpdate")
+ logger.Debugw(ctx, "device-update", log.Fields{"device-id": device.Id, "device": device})
+
+ if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
+ if err := agent.updateDeviceUsingAdapterData(ctx, device); err != nil {
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", device.Id)
+}
+
+func (dMgr *Manager) DeviceStateUpdate(ctx context.Context, ds *ic.DeviceStateFilter) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeviceStateUpdate")
+ logger.Debugw(ctx, "device-state-update", log.Fields{"device-id": ds.DeviceId, "operStatus": ds.OperStatus, "connStatus": ds.ConnStatus})
+
+ if agent := dMgr.getDeviceAgent(ctx, ds.DeviceId); agent != nil {
+ if err := agent.updateDeviceStatus(ctx, ds.OperStatus, ds.ConnStatus); err != nil {
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", ds.DeviceId)
+}
+
+func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, dd *ic.DeviceDiscovery) (*voltha.Device, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildDeviceDetected")
+ logger.Debugw(ctx, "child-device-detected",
+ log.Fields{
+ "parent-device-id": dd.ParentId,
+ "parentPortNo": dd.ParentPortNo,
+ "deviceType": dd.ChildDeviceType,
+ "channelId": dd.ChannelId,
+ "vendorId": dd.VendorId,
+ "serialNumber": dd.SerialNumber,
+ "onuId": dd.OnuId,
+ })
+
+ var err error
+ if dd.ChildDeviceType == "" && dd.VendorId != "" {
+ logger.Debug(ctx, "device-type-is-nil-fetching-device-type")
+ if dd.ChildDeviceType, err = dMgr.adapterMgr.GetAdapterTypeByVendorID(dd.VendorId); err != nil {
+ return nil, err
+ }
+ }
+ //if no match found for the vendorid,report adapter with the custom error message
+ if dd.ChildDeviceType == "" {
+ logger.Errorw(ctx, "failed-to-fetch-adapter-name ", log.Fields{"vendorId": dd.VendorId})
+ return nil, status.Errorf(codes.NotFound, "%s", dd.VendorId)
+ }
+
+ // Create the ONU device
+ childDevice := &voltha.Device{}
+ childDevice.Type = dd.ChildDeviceType
+ childDevice.ParentId = dd.ParentId
+ childDevice.ParentPortNo = uint32(dd.ParentPortNo)
+ childDevice.VendorId = dd.VendorId
+ childDevice.SerialNumber = dd.SerialNumber
+ childDevice.Root = false
+
+ // Get parent device type
+ pAgent := dMgr.getDeviceAgent(ctx, dd.ParentId)
+ if pAgent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", dd.ParentId)
+ }
+ if pAgent.deviceType == "" {
+ pDevice, err := pAgent.getDeviceReadOnly(ctx)
+ logger.Errorw(ctx, "device-type-not-set", log.Fields{"parent-device": pDevice, "error": err})
+ return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", dd.ParentId)
+ }
+
+ if device, err := dMgr.GetChildDevice(ctx, &ic.ChildDeviceFilter{
+ ParentId: dd.ParentId,
+ SerialNumber: dd.SerialNumber,
+ OnuId: dd.OnuId,
+ ParentPortNo: dd.ParentPortNo}); err == nil {
+ logger.Warnw(ctx, "child-device-exists", log.Fields{"parent-device-id": dd.ParentId, "serialNumber": dd.SerialNumber})
+ return device, status.Errorf(codes.AlreadyExists, "%s", dd.SerialNumber)
+ }
+
+ //Get parent endpoint
+ pEndPoint, err := dMgr.adapterMgr.GetAdapterEndpoint(ctx, pAgent.deviceID, pAgent.deviceType)
+ if err != nil {
+ logger.Errorw(ctx, "endpoint-error", log.Fields{"error": err, "parent-id": pAgent.deviceID, "parent-device-type": pAgent.deviceType})
+ return nil, status.Errorf(codes.NotFound, "parent-endpoint-%s", dd.ParentId)
+ }
+
+ childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: dd.ParentId, DeviceType: pAgent.deviceType, ChannelId: dd.ChannelId, OnuId: dd.OnuId, AdapterEndpoint: pEndPoint}
+
+ // Set child device ID -- needed to get the device endpoint
+ childDevice.Id = utils.CreateDeviceID()
+
+ // Set the child adapter endpoint
+ childDevice.AdapterEndpoint, err = dMgr.adapterMgr.GetAdapterEndpoint(ctx, childDevice.Id, childDevice.Type)
+ if err != nil {
+ return nil, status.Errorf(codes.NotFound, "child-endpoint-%s", childDevice.Id)
+ }
+
+ // Create and start a device agent for that device
+ agent := newAgent(childDevice, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout)
+ insertedChildDevice, err := agent.start(ctx, false, childDevice)
+ if err != nil {
+ logger.Errorw(ctx, "error-starting-child-device", log.Fields{"parent-device-id": childDevice.ParentId, "child-device-id": agent.deviceID, "error": err})
+ return nil, err
+ }
+ dMgr.addDeviceAgentToMap(agent)
+
+ // Activate the child device
+ if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
+ go func() {
+ err := agent.enableDevice(utils.WithSpanAndRPCMetadataFromContext(ctx))
+ if err != nil {
+ logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err, "device-id": agent.deviceID})
+ }
+ }()
+ }
+
+ return insertedChildDevice, nil
+}
+
+func (dMgr *Manager) GetChildDevice(ctx context.Context, df *ic.ChildDeviceFilter) (*voltha.Device, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetChildDevice")
+ logger.Debugw(ctx, "get-child-device", log.Fields{"filter": df})
+
+ parentDevicePorts, err := dMgr.listDevicePorts(ctx, df.ParentId)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
+ if len(childDeviceIds) == 0 {
+ logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": df.ParentId, "serial-number": df.SerialNumber, "onu-id": df.OnuId})
+ return nil, status.Errorf(codes.NotFound, "%s", df.ParentId)
+ }
+
+ var foundChildDevice *voltha.Device
+ for childDeviceID := range childDeviceIds {
+ var found bool
+ if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
+
+ foundOnuID := false
+ if searchDevice.ProxyAddress.OnuId == uint32(df.OnuId) {
+ if searchDevice.ParentPortNo == uint32(df.ParentPortNo) {
+ logger.Debugw(ctx, "found-child-by-onu-id", log.Fields{"parent-device-id": df.ParentId, "onuId": df.OnuId})
+ foundOnuID = true
+ }
+ }
+
+ foundSerialNumber := false
+ if searchDevice.SerialNumber == df.SerialNumber {
+ logger.Debugw(ctx, "found-child-by-serial-number", log.Fields{"parent-device-id": df.ParentId, "serialNumber": df.SerialNumber})
+ foundSerialNumber = true
+ }
+
+ // if both onuId and serialNumber are provided both must be true for the device to be found
+ // otherwise whichever one found a match is good enough
+ if df.OnuId > 0 && df.SerialNumber != "" {
+ found = foundOnuID && foundSerialNumber
+ } else {
+ found = foundOnuID || foundSerialNumber
+ }
+
+ if found {
+ foundChildDevice = searchDevice
+ break
+ }
+ }
+ }
+
+ if foundChildDevice != nil {
+ logger.Debugw(ctx, "child-device-found", log.Fields{"parent-device-id": df.ParentId, "foundChildDevice": foundChildDevice})
+ return foundChildDevice, nil
+ }
+
+ logger.Debugw(ctx, "child-device-not-found", log.Fields{"parent-device-id": df.ParentId,
+ "serialNumber": df.SerialNumber, "onuId": df.OnuId, "parentPortNo": df.ParentPortNo})
+ return nil, status.Errorf(codes.NotFound, "%s", df.ParentId)
+}
+
+// PortsStateUpdate updates the operational status of all ports on the device
+func (dMgr *Manager) PortsStateUpdate(ctx context.Context, ps *ic.PortStateFilter) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "PortsStateUpdate")
+ logger.Debugw(ctx, "ports-state-update", log.Fields{"device-id": ps.DeviceId})
+
+ agent := dMgr.getDeviceAgent(ctx, ps.DeviceId)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", ps.DeviceId)
+ }
+ if ps.OperStatus != voltha.OperStatus_ACTIVE && ps.OperStatus != voltha.OperStatus_UNKNOWN {
+ return nil, status.Error(codes.Unimplemented, "state-change-not-implemented")
+ }
+ if err := agent.updatePortsOperState(ctx, ps.PortTypeFilter, ps.OperStatus); err != nil {
+ logger.Warnw(ctx, "ports-state-update-failed", log.Fields{"device-id": ps.DeviceId, "error": err})
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+}
+
+//ChildDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
+//cannot manage the child devices. This will trigger the Core to disable all the child devices.
+func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentID *common.ID) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildDevicesLost")
+ logger.Debugw(ctx, "child-devices-lost", log.Fields{"parent-id": parentID.Id})
+
+ parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentID.Id)
+ if err != nil {
+ logger.Warnw(ctx, "failed-getting-device", log.Fields{"parent-device-id": parentID.Id, "error": err})
+ return nil, err
+ }
+ if err = dMgr.DisableAllChildDevices(ctx, parentDevice); err != nil {
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+}
+
+//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
+// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
+func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID *common.ID) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildDevicesDetected")
+ logger.Debugw(ctx, "child-devices-detected", log.Fields{"parent-device-id": parentDeviceID})
+
+ parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID.Id)
+ if err != nil {
+ logger.Warnw(ctx, "failed-getting-device", log.Fields{"device-id": parentDeviceID.Id, "error": err})
+ return nil, err
+ }
+ childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
+ if len(childDeviceIds) == 0 {
+ logger.Debugw(ctx, "no-child-device", log.Fields{"parent-device-id": parentDeviceID.Id})
+ }
+ allChildEnableRequestSent := true
+ for childDeviceID := range childDeviceIds {
+ if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
+ // Run the children re-registration in its own routine
+ go func(ctx context.Context) {
+ err = agent.enableDevice(ctx)
+ if err != nil {
+ logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
+ }
+ }(log.WithSpanFromContext(context.Background(), ctx))
+ } else {
+ err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
+ logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parent-device-id": parentDeviceID.Id, "childId": childDeviceID})
+ allChildEnableRequestSent = false
+ }
+ }
+ if !allChildEnableRequestSent {
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+}
+
+// GetChildDeviceWithProxyAddress will return a device based on proxy address
+func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetChildDeviceWithProxyAddress")
+
+ logger.Debugw(ctx, "get-child-device-with-proxy-address", log.Fields{"proxyAddress": proxyAddress})
+
+ parentDevicePorts, err := dMgr.listDevicePorts(ctx, proxyAddress.DeviceId)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
+ if len(childDeviceIds) == 0 {
+ logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": proxyAddress.DeviceId})
+ return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
+ }
+
+ var foundChildDevice *voltha.Device
+ for childDeviceID := range childDeviceIds {
+ if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
+ if searchDevice.ProxyAddress == proxyAddress {
+ foundChildDevice = searchDevice
+ break
+ }
+ }
+ }
+
+ if foundChildDevice != nil {
+ logger.Debugw(ctx, "child-device-found", log.Fields{"proxyAddress": proxyAddress})
+ return foundChildDevice, nil
+ }
+
+ logger.Warnw(ctx, "child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
+ return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
+}
+
+func (dMgr *Manager) GetPorts(ctx context.Context, pf *ic.PortFilter) (*voltha.Ports, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetPorts")
+ logger.Debugw(ctx, "get-ports", log.Fields{"device-id": pf.DeviceId, "portType": pf.PortType})
+
+ agent := dMgr.getDeviceAgent(ctx, pf.DeviceId)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", pf.DeviceId)
+ }
+ return agent.getPorts(ctx, pf.PortType), nil
+}
+
+func (dMgr *Manager) GetChildDevices(ctx context.Context, parentDeviceID *common.ID) (*voltha.Devices, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetChildDevices")
+
+ logger.Debugw(ctx, "get-child-devices", log.Fields{"parent-device-id": parentDeviceID.Id})
+ return dMgr.getAllChildDevices(ctx, parentDeviceID.Id)
+}
+
+func (dMgr *Manager) ChildrenStateUpdate(ctx context.Context, ds *ic.DeviceStateFilter) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildrenStateUpdate")
+ logger.Debugw(ctx, "children-state-update", log.Fields{"parent-device-id": ds.ParentDeviceId, "operStatus": ds.OperStatus, "connStatus": ds.ConnStatus})
+
+ parentDevicePorts, err := dMgr.listDevicePorts(ctx, ds.ParentDeviceId)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
+ if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
+ if err = agent.updateDeviceStatus(ctx, ds.OperStatus, ds.ConnStatus); err != nil {
+ return nil, status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
+ }
+ }
+ }
+ return &empty.Empty{}, nil
+}
+
+func (dMgr *Manager) PortStateUpdate(ctx context.Context, ps *ic.PortState) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "PortStateUpdate")
+ logger.Debugw(ctx, "port-state-update", log.Fields{"device-id": ps.DeviceId, "portType": ps.PortType, "portNo": ps.PortNo, "operStatus": ps.OperStatus})
+
+ if agent := dMgr.getDeviceAgent(ctx, ps.DeviceId); agent != nil {
+ if err := agent.updatePortState(ctx, ps.PortType, ps.PortNo, ps.OperStatus); err != nil {
+ logger.Errorw(ctx, "updating-port-state-failed", log.Fields{"device-id": ps.DeviceId, "portNo": ps.PortNo, "error": err})
+ return nil, err
+ }
+ // Notify the logical device manager to change the port state
+ // Do this for NNI and UNIs only. PON ports are not known by logical device
+ if ps.PortType == voltha.Port_ETHERNET_NNI || ps.PortType == voltha.Port_ETHERNET_UNI {
+ go func() {
+ err := dMgr.logicalDeviceMgr.updatePortState(log.WithSpanFromContext(context.Background(), ctx), ps.DeviceId, ps.PortNo, ps.OperStatus)
+ if err != nil {
+ // While we want to handle (catch) and log when
+ // an update to a port was not able to be
+ // propagated to the logical port, we can report
+ // it as a warning and not an error because it
+ // doesn't stop or modify processing.
+ // TODO: VOL-2707
+ logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
+ }
+ }()
+ }
+ return &empty.Empty{}, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", ps.DeviceId)
+}
+
+func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID *common.ID) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeleteAllPorts")
+ logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": deviceID.Id})
+
+ if agent := dMgr.getDeviceAgent(ctx, deviceID.Id); agent != nil {
+ if err := agent.deleteAllPorts(ctx); err != nil {
+ return nil, err
+ }
+ // 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.getDeviceReadOnly(ctx, deviceID.Id); err == nil {
+ go func() {
+ subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
+ if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(subCtx, device); err != nil {
+ logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
+ }
+ }()
+ } else {
+ logger.Warnw(ctx, "failed-to-retrieve-device", log.Fields{"device-id": deviceID.Id})
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", deviceID.Id)
+}
+
+// GetDevicePort returns the port details for a specific device port entry
+func (dMgr *Manager) GetDevicePort(ctx context.Context, pf *ic.PortFilter) (*voltha.Port, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetDevicePort")
+ logger.Debugw(ctx, "get-device-port", log.Fields{"device-id": pf.DeviceId})
+
+ agent := dMgr.getDeviceAgent(ctx, pf.DeviceId)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "device-%s", pf.DeviceId)
+ }
+ return agent.getDevicePort(pf.Port)
+}
+
+// DevicePMConfigUpdate updates the pm configs as defined by the adapter.
+func (dMgr *Manager) DevicePMConfigUpdate(ctx context.Context, pc *voltha.PmConfigs) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DevicePMConfigUpdate")
+ logger.Debugw(ctx, "device-pm-config-update", log.Fields{"device-id": pc.Id})
+
+ if pc.Id == "" {
+ return nil, status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
+ }
+ if agent := dMgr.getDeviceAgent(ctx, pc.Id); agent != nil {
+ if err := agent.initPmConfigs(ctx, pc); err != nil {
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", pc.Id)
+}
+
+// SendPacketIn receives packetIn request from adapter
+func (dMgr *Manager) SendPacketIn(ctx context.Context, pi *ic.PacketIn) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "SendPacketIn")
+ logger.Debugw(ctx, "packet-in", log.Fields{"device-id": pi.DeviceId, "port": pi.Port})
+
+ // Get the logical device Id based on the deviceId
+ var device *voltha.Device
+ var err error
+ if device, err = dMgr.getDeviceReadOnly(ctx, pi.DeviceId); err != nil {
+ logger.Errorw(ctx, "device-not-found", log.Fields{"device-id": pi.DeviceId})
+ return nil, err
+ }
+ if !device.Root {
+ logger.Errorw(ctx, "device-not-root", log.Fields{"device-id": pi.DeviceId})
+ return nil, status.Errorf(codes.FailedPrecondition, "%s", pi.DeviceId)
+ }
+
+ if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, pi.Port, pi.Packet); err != nil {
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+}
+
+func (dMgr *Manager) DeviceReasonUpdate(ctx context.Context, dr *ic.DeviceReason) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeviceReasonUpdate")
+ logger.Debugw(ctx, "update-device-reason", log.Fields{"device-id": dr.DeviceId, "reason": dr.Reason})
+
+ if agent := dMgr.getDeviceAgent(ctx, dr.DeviceId); agent != nil {
+ if err := agent.updateDeviceReason(ctx, dr.Reason); err != nil {
+ return nil, err
+ }
+ return &empty.Empty{}, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", dr.DeviceId)
+}
+
+func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID *common.ID) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ReconcileChildDevices")
+ logger.Debugw(ctx, "reconcile-child-devices", log.Fields{"device-id": parentDeviceID.Id})
+
+ numberOfDevicesToReconcile := 0
+ dMgr.deviceAgents.Range(func(key, value interface{}) bool {
+ deviceAgent, ok := value.(*Agent)
+ if ok && deviceAgent.parentID == parentDeviceID.Id {
+ go deviceAgent.ReconcileDevice(utils.WithNewSpanAndRPCMetadataContext(ctx, "ReconcileChildDevices"))
+ numberOfDevicesToReconcile++
+ }
+ return true
+ })
+ logger.Debugw(ctx, "reconciling-child-devices-initiated", log.Fields{"parent-device-id": parentDeviceID.Id, "number-of-child-devices-to-reconcile": numberOfDevicesToReconcile})
+ return &empty.Empty{}, nil
+}
+
+func (dMgr *Manager) UpdateImageDownload(ctx context.Context, img *voltha.ImageDownload) (*empty.Empty, error) {
+ ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "UpdateImageDownload")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "update-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
+
+ if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
+ if err := agent.updateImageDownload(ctx, img); err != nil {
+ logger.Debugw(ctx, "update-image-download-failed", log.Fields{"err": err, "image-name": img.Name})
+ return nil, err
+ }
+ } else {
+ return nil, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ return &empty.Empty{}, nil
+}
diff --git a/rw_core/core/device/manager_state_callback.go b/rw_core/core/device/manager_state_callback.go
new file mode 100644
index 0000000..6bd42eb
--- /dev/null
+++ b/rw_core/core/device/manager_state_callback.go
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package device
+
+import (
+ "context"
+
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/core"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+//
+//CreateLogicalDevice creates logical device in core
+func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
+ logger.Info(ctx, "create-logical-device")
+ // Verify whether the logical device has already been created
+ if cDevice.ParentId != "" {
+ logger.Debugw(ctx, "parent-device-already-exist", log.Fields{"device-id": cDevice.Id, "logical-device-id": cDevice.Id})
+ return nil
+ }
+ var err error
+ if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
+ logger.Warnw(ctx, "create-logical-device-error", log.Fields{"device": cDevice})
+ return err
+ }
+ return nil
+}
+
+// DeleteLogicalDevice deletes logical device from core
+func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
+ logger.Info(ctx, "delete-logical-device")
+ var err error
+ if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
+ logger.Warnw(ctx, "delete-logical-device-error", log.Fields{"device-id": cDevice.Id})
+ return err
+ }
+ // Remove the logical device Id from the parent device
+ logicalID := ""
+ dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
+ return nil
+}
+
+// DeleteLogicalPorts removes the logical ports associated with that deviceId
+func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
+ logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
+ if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
+ // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
+ logger.Warnw(ctx, "delete-logical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
+ }
+ return nil
+}
+
+// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
+func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
+ logger.Info(ctx, "setup-uni-logical-ports")
+ cDevicePorts, err := dMgr.listDevicePorts(ctx, cDevice.Id)
+ if err != nil {
+ return err
+ }
+ if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice, cDevicePorts); err != nil {
+ logger.Warnw(ctx, "setup-uni-logical-ports-error", log.Fields{"device": cDevice, "err": err})
+ return err
+ }
+ return nil
+}
+
+// RunPostDeviceDelete removes any reference of this device
+func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
+ logger.Infow(ctx, "run-post-device-delete", log.Fields{"device-id": cDevice.Id})
+ dMgr.stopManagingDevice(ctx, cDevice.Id)
+ return nil
+}
+
+//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
+func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
+ logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
+ if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
+ // Just log error as logical device may already have been deleted
+ logger.Warnw(ctx, "delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
+ }
+ return nil
+}
+
+//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
+func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
+ logger.Debugw(ctx, "delete-all-child-devices", log.Fields{"parent-device-id": parentCurrDevice.Id})
+ force := false
+ // Get the parent device Transient state, if its FORCE_DELETED(go for force delete for child devices)
+ // So in cases when this handler is getting called other than DELETE operation, no force option would be used.
+ agent := dMgr.getDeviceAgent(ctx, parentCurrDevice.Id)
+ if agent == nil {
+ return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
+ }
+
+ force = agent.getTransientState() == core.DeviceTransientState_FORCE_DELETING
+
+ ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
+ for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
+ if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
+ logger.Debugw(ctx, "invoking-delete-device", log.Fields{"device-id": childDeviceID, "force-delete": force})
+ if force {
+ if err := agent.deleteDeviceForce(ctx); err != nil {
+ logger.Warnw(ctx, "failure-delete-device-force", log.Fields{"device-id": childDeviceID,
+ "error": err.Error()})
+ }
+ } else {
+ if err := agent.deleteDevice(ctx); err != nil {
+ logger.Warnw(ctx, "failure-delete-device", log.Fields{"device-id": childDeviceID,
+ "error": err.Error()})
+ }
+ }
+ // No further action is required here. The deleteDevice will change the device state where the resulting
+ // callback will take care of cleaning the child device agent.
+ }
+ }
+ return nil
+}
+
+//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
+func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
+ logger.Debugw(ctx, "delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
+ if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
+ if err := agent.deleteAllFlows(ctx); err != nil {
+ logger.Errorw(ctx, "error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
+ return err
+ }
+ return nil
+ }
+ return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
+}
+
+// ChildDeviceLost calls parent adapter to delete child device and all its references
+func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
+ logger.Debugw(ctx, "child-device-lost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
+ if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
+ if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
+ // Just log the message and let the remaining pipeline proceed.
+ logger.Warnw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
+ }
+ }
+ // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
+ return nil
+}
diff --git a/rw_core/core/device/manager_test.go b/rw_core/core/device/manager_test.go_todo
similarity index 98%
rename from rw_core/core/device/manager_test.go
rename to rw_core/core/device/manager_test.go_todo
index 1594b6e..e0156bb 100644
--- a/rw_core/core/device/manager_test.go
+++ b/rw_core/core/device/manager_test.go_todo
@@ -29,11 +29,11 @@
"github.com/opencord/voltha-go/rw_core/config"
"github.com/opencord/voltha-go/rw_core/core/adapter"
tst "github.com/opencord/voltha-go/rw_core/test"
- "github.com/opencord/voltha-lib-go/v5/pkg/db"
- "github.com/opencord/voltha-lib-go/v5/pkg/events"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-protos/v4/go/common"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db"
+ "github.com/opencord/voltha-lib-go/v7/pkg/events"
+ "github.com/opencord/voltha-lib-go/v7/pkg/kafka"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"github.com/phayes/freeport"
"github.com/stretchr/testify/assert"
)
diff --git a/rw_core/core/device/meter/common.go b/rw_core/core/device/meter/common.go
index 773c0b7..7ecb52c 100644
--- a/rw_core/core/device/meter/common.go
+++ b/rw_core/core/device/meter/common.go
@@ -18,7 +18,7 @@
package meter
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/meter/loader.go b/rw_core/core/device/meter/loader.go
index 42f4264..52cdb9a 100644
--- a/rw_core/core/device/meter/loader.go
+++ b/rw_core/core/device/meter/loader.go
@@ -15,12 +15,13 @@
import (
"context"
"fmt"
+ "sync"
+
"github.com/opencord/voltha-go/db/model"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
- "sync"
)
// Loader hides all low-level locking & synchronization related to meter state updates
diff --git a/rw_core/core/device/mock_kafka.go b/rw_core/core/device/mock_kafka.go
index 54ee427..68c8aa5 100644
--- a/rw_core/core/device/mock_kafka.go
+++ b/rw_core/core/device/mock_kafka.go
@@ -15,7 +15,7 @@
*/
// Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/opencord/voltha-lib-go/v5/pkg/kafka (interfaces: InterContainerProxy)
+// Source: github.com/opencord/voltha-lib-go/v7/pkg/kafka (interfaces: InterContainerProxy)
// Package device is a generated GoMock package.
package device
@@ -26,7 +26,7 @@
gomock "github.com/golang/mock/gomock"
any "github.com/golang/protobuf/ptypes/any"
- kafka "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
+ kafka "github.com/opencord/voltha-lib-go/v7/pkg/kafka"
)
// MockInterContainerProxy is a mock of InterContainerProxy interface.
diff --git a/rw_core/core/device/port/common.go b/rw_core/core/device/port/common.go
index fede329..c8b3538 100644
--- a/rw_core/core/device/port/common.go
+++ b/rw_core/core/device/port/common.go
@@ -18,7 +18,7 @@
package port
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/port/loader.go b/rw_core/core/device/port/loader.go
index e1017bd..823d1dd 100644
--- a/rw_core/core/device/port/loader.go
+++ b/rw_core/core/device/port/loader.go
@@ -22,8 +22,8 @@
"sync"
"github.com/opencord/voltha-go/db/model"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
diff --git a/rw_core/core/device/remote/adapter_proxy.go b/rw_core/core/device/remote/adapter_proxy.go
deleted file mode 100755
index 77b9d1c..0000000
--- a/rw_core/core/device/remote/adapter_proxy.go
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package remote
-
-import (
- "context"
-
- "github.com/opencord/voltha-protos/v4/go/common"
-
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/extension"
- ic "github.com/opencord/voltha-protos/v4/go/inter_container"
- ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
-)
-
-// AdapterProxy represents adapter proxy attributes
-type AdapterProxy struct {
- kafka.EndpointManager
- coreTopic string
- kafkaICProxy kafka.InterContainerProxy
-}
-
-// NewAdapterProxy will return adapter proxy instance
-func NewAdapterProxy(kafkaProxy kafka.InterContainerProxy, coreTopic string, endpointManager kafka.EndpointManager) *AdapterProxy {
- return &AdapterProxy{
- EndpointManager: endpointManager,
- kafkaICProxy: kafkaProxy,
- coreTopic: coreTopic,
- }
-}
-
-func (ap *AdapterProxy) getCoreTopic() kafka.Topic {
- return kafka.Topic{Name: ap.coreTopic}
-}
-
-func (ap *AdapterProxy) getAdapterTopic(ctx context.Context, deviceID string, adapterType string) (*kafka.Topic, error) {
-
- endpoint, err := ap.GetEndpoint(ctx, deviceID, adapterType)
- if err != nil {
- return nil, err
- }
-
- return &kafka.Topic{Name: string(endpoint)}, nil
-}
-
-func (ap *AdapterProxy) sendRPC(ctx context.Context, rpc string, toTopic *kafka.Topic, replyToTopic *kafka.Topic,
- waitForResponse bool, deviceID string, kvArgs ...*kafka.KVArg) (chan *kafka.RpcResponse, error) {
-
- // Sent the request to kafka
- respChnl := ap.kafkaICProxy.InvokeAsyncRPC(ctx, rpc, toTopic, replyToTopic, waitForResponse, deviceID, kvArgs...)
-
- // Wait for first response which would indicate whether the request was successfully sent to kafka.
- firstResponse, ok := <-respChnl
- if !ok || firstResponse.MType != kafka.RpcSent {
- logger.Errorw(ctx, "failure to request to kafka", log.Fields{"rpc": rpc, "device-id": deviceID, "error": firstResponse.Err})
- return nil, firstResponse.Err
- }
- // return the kafka channel for the caller to wait for the response of the RPC call
- return respChnl, nil
-}
-
-// AdoptDevice invokes adopt device rpc
-func (ap *AdapterProxy) AdoptDevice(ctx context.Context, device *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "AdoptDevice", log.Fields{"device-id": device.Id})
- rpc := "adopt_device"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- }
- replyToTopic := ap.getCoreTopic()
- logger.Debugw(ctx, "adoptDevice-send-request", log.Fields{"device-id": device.Id, "deviceType": device.Type, "serialNumber": device.SerialNumber})
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// DisableDevice invokes disable device rpc
-func (ap *AdapterProxy) DisableDevice(ctx context.Context, device *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "DisableDevice", log.Fields{"device-id": device.Id})
- rpc := "disable_device"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// ReEnableDevice invokes reenable device rpc
-func (ap *AdapterProxy) ReEnableDevice(ctx context.Context, device *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "ReEnableDevice", log.Fields{"device-id": device.Id})
- rpc := "reenable_device"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// RebootDevice invokes reboot device rpc
-func (ap *AdapterProxy) RebootDevice(ctx context.Context, device *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "RebootDevice", log.Fields{"device-id": device.Id})
- rpc := "reboot_device"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// DeleteDevice invokes delete device rpc
-func (ap *AdapterProxy) DeleteDevice(ctx context.Context, device *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "DeleteDevice", log.Fields{"device-id": device.Id})
- rpc := "delete_device"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// GetOfpDeviceInfo invokes get ofp device info rpc
-func (ap *AdapterProxy) GetOfpDeviceInfo(ctx context.Context, device *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "GetOfpDeviceInfo", log.Fields{"device-id": device.Id})
- rpc := "get_ofp_device_info"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// ReconcileDevice invokes reconcile device rpc
-func (ap *AdapterProxy) ReconcileDevice(ctx context.Context, device *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "ReconcileDevice", log.Fields{"device-id": device.Id})
- rpc := "reconcile_device"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// DownloadImage invokes download image rpc
-func (ap *AdapterProxy) DownloadImage(ctx context.Context, device *voltha.Device, download *voltha.ImageDownload) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "DownloadImage", log.Fields{"device-id": device.Id, "image": download.Name})
- rpc := "download_image"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "request", Value: download},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// GetImageDownloadStatus invokes get image download status rpc
-func (ap *AdapterProxy) GetImageDownloadStatus(ctx context.Context, device *voltha.Device, download *voltha.ImageDownload) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "GetImageDownloadStatus", log.Fields{"device-id": device.Id, "image": download.Name})
- rpc := "get_image_download_status"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "request", Value: download},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// CancelImageDownload invokes cancel image download rpc
-func (ap *AdapterProxy) CancelImageDownload(ctx context.Context, device *voltha.Device, download *voltha.ImageDownload) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "CancelImageDownload", log.Fields{"device-id": device.Id, "image": download.Name})
- rpc := "cancel_image_download"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "request", Value: download},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// ActivateImageUpdate invokes activate image update rpc
-func (ap *AdapterProxy) ActivateImageUpdate(ctx context.Context, device *voltha.Device, download *voltha.ImageDownload) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "ActivateImageUpdate", log.Fields{"device-id": device.Id, "image": download.Name})
- rpc := "activate_image_update"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "request", Value: download},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// RevertImageUpdate invokes revert image update rpc
-func (ap *AdapterProxy) RevertImageUpdate(ctx context.Context, device *voltha.Device, download *voltha.ImageDownload) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "RevertImageUpdate", log.Fields{"device-id": device.Id, "image": download.Name})
- rpc := "revert_image_update"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "request", Value: download},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) PacketOut(ctx context.Context, deviceType string, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "PacketOut", log.Fields{"device-id": deviceID, "device-type": deviceType, "out-port": outPort})
- toTopic, err := ap.getAdapterTopic(ctx, deviceID, deviceType)
- if err != nil {
- return nil, err
- }
- rpc := "receive_packet_out"
- args := []*kafka.KVArg{
- {Key: "deviceId", Value: &ic.StrType{Val: deviceID}},
- {Key: "outPort", Value: &ic.IntType{Val: int64(outPort)}},
- {Key: "packet", Value: packet},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, deviceID, args...)
-}
-
-// UpdateFlowsBulk invokes update flows bulk rpc
-func (ap *AdapterProxy) UpdateFlowsBulk(ctx context.Context, device *voltha.Device, flows map[uint64]*ofp.OfpFlowStats, groups map[uint32]*voltha.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "UpdateFlowsBulk", log.Fields{"device-id": device.Id, "flow-count": len(flows), "group-count": len(groups), "flow-metadata": flowMetadata})
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- rpc := "update_flows_bulk"
-
- ctr, flowSlice := 0, make([]*ofp.OfpFlowStats, len(flows))
- for _, flow := range flows {
- flowSlice[ctr] = flow
- ctr++
- }
- ctr, groupSlice := 0, make([]*ofp.OfpGroupEntry, len(groups))
- for _, group := range groups {
- groupSlice[ctr] = group
- ctr++
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "flows", Value: &voltha.Flows{Items: flowSlice}},
- {Key: "groups", Value: &voltha.FlowGroups{Items: groupSlice}},
- {Key: "flow_metadata", Value: flowMetadata},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(log.WithSpanFromContext(context.TODO(), ctx), rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// UpdateFlowsIncremental invokes update flows incremental rpc
-func (ap *AdapterProxy) UpdateFlowsIncremental(ctx context.Context, device *voltha.Device, flowChanges *ofp.FlowChanges, groupChanges *ofp.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "UpdateFlowsIncremental",
- log.Fields{
- "device-id": device.Id,
- "flow-to-add-count": len(flowChanges.ToAdd.Items),
- "flow-to-delete-count": len(flowChanges.ToRemove.Items),
- "group-to-add-count": len(groupChanges.ToAdd.Items),
- "group-to-delete-count": len(groupChanges.ToRemove.Items),
- "group-to-update-count": len(groupChanges.ToUpdate.Items),
- })
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- rpc := "update_flows_incrementally"
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "flow_changes", Value: flowChanges},
- {Key: "group_changes", Value: groupChanges},
- {Key: "flow_metadata", Value: flowMetadata},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(log.WithSpanFromContext(context.TODO(), ctx), rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// UpdatePmConfigs invokes update pm configs rpc
-func (ap *AdapterProxy) UpdatePmConfigs(ctx context.Context, device *voltha.Device, pmConfigs *voltha.PmConfigs) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "UpdatePmConfigs", log.Fields{"device-id": device.Id, "pm-configs-id": pmConfigs.Id})
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- rpc := "update_pm_config"
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "pm_configs", Value: pmConfigs},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// SimulateAlarm invokes simulate alarm rpc
-func (ap *AdapterProxy) SimulateAlarm(ctx context.Context, device *voltha.Device, simulateReq *voltha.SimulateAlarmRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "SimulateAlarm", log.Fields{"device-id": device.Id, "simulate-req-id": simulateReq.Id})
- rpc := "simulate_alarm"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "device", Value: device},
- {Key: "request", Value: simulateReq},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) DisablePort(ctx context.Context, device *voltha.Device, port *voltha.Port) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "DisablePort", log.Fields{"device-id": device.Id, "port-no": port.PortNo})
- rpc := "disable_port"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceId", Value: &ic.StrType{Val: device.Id}},
- {Key: "port", Value: port},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) EnablePort(ctx context.Context, device *voltha.Device, port *voltha.Port) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "EnablePort", log.Fields{"device-id": device.Id, "port-no": port.PortNo})
- rpc := "enable_port"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceId", Value: &ic.StrType{Val: device.Id}},
- {Key: "port", Value: port},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-// ChildDeviceLost invokes child device_lost rpc
-func (ap *AdapterProxy) ChildDeviceLost(ctx context.Context, deviceType string, childDevice *voltha.Device) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "ChildDeviceLost",
- log.Fields{"device-id": childDevice.ParentId, "parent-port-no": childDevice.ParentPortNo,
- "onu-id": childDevice.ProxyAddress.OnuId, "serial-number": childDevice.SerialNumber})
- rpc := "child_device_lost"
- toTopic, err := ap.getAdapterTopic(ctx, childDevice.ParentId, deviceType)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "childDevice", Value: childDevice},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, childDevice.ParentId, args...)
-}
-
-func (ap *AdapterProxy) StartOmciTest(ctx context.Context, device *voltha.Device, omcitestrequest *voltha.OmciTestRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "Omci_test_Request_adapter_proxy", log.Fields{"device": device, "omciTestRequest": omcitestrequest})
- rpc := "start_omci_test"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- // Use a device specific topic as we are the only core handling requests for this device
- replyToTopic := ap.getCoreTopic()
- // TODO: Perhaps this should have used omcitestrequest.uuid as the second argument rather
- // than including the whole request, which is (deviceid, uuid)
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id,
- &kafka.KVArg{Key: "device", Value: device},
- &kafka.KVArg{Key: "omcitestrequest", Value: omcitestrequest})
-}
-
-func (ap *AdapterProxy) GetExtValue(ctx context.Context, pdevice *voltha.Device, cdevice *voltha.Device, id string, valuetype voltha.ValueType_Type) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "GetExtValue", log.Fields{"device-id": pdevice.Id, "onuid": id})
- rpc := "get_ext_value"
- toTopic, err := ap.getAdapterTopic(ctx, pdevice.Id, pdevice.Adapter)
- if err != nil {
- return nil, err
- }
- // Use a device specific topic to send the request. The adapter handling the device creates a device
- // specific topic
- args := []*kafka.KVArg{
- {
- Key: "pDeviceId",
- Value: &ic.StrType{Val: pdevice.Id},
- },
- {
- Key: "device",
- Value: cdevice,
- },
- {
- Key: "valuetype",
- Value: &ic.IntType{Val: int64(valuetype)},
- }}
-
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, pdevice.Id, args...)
-}
-
-// SetExtValue set some given configs or value
-func (ap *AdapterProxy) SetExtValue(ctx context.Context, device *voltha.Device, value *voltha.ValueSet) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "SetExtValue", log.Fields{"device-id": value.Id})
- rpc := "set_ext_value"
- toTopic, err := ap.getAdapterTopic(ctx, value.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- // Use a device specific topic to send the request. The adapter handling the device creates a device
- // specific topic
- args := []*kafka.KVArg{
- {
- Key: "value",
- Value: value,
- },
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, value.Id, args...)
-}
-
-// GetSingleValue get a value from the adapter, based on the request type
-func (ap *AdapterProxy) GetSingleValue(ctx context.Context, adapterType string, request *extension.SingleGetValueRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "GetSingleValue", log.Fields{"device-id": request.TargetId})
- rpc := "single_get_value_request"
- toTopic, err := ap.getAdapterTopic(ctx, request.TargetId, adapterType)
- if err != nil {
- return nil, err
- }
-
- // Use a device specific topic to send the request. The adapter handling the device creates a device
- // specific topic
- args := []*kafka.KVArg{
- {
- Key: "request",
- Value: request,
- },
- }
-
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, request.TargetId, args...)
-}
-
-// SetSingleValue set a single value on the adapter, based on the request type
-func (ap *AdapterProxy) SetSingleValue(ctx context.Context, adapterType string, request *extension.SingleSetValueRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "SetSingleValue", log.Fields{"device-id": request.TargetId})
- rpc := "single_set_value_request"
- toTopic, err := ap.getAdapterTopic(ctx, request.TargetId, adapterType)
- if err != nil {
- return nil, err
- }
-
- // Use a device specific topic to send the request. The adapter handling the device creates a device
- // specific topic
- args := []*kafka.KVArg{
- {
- Key: "request",
- Value: request,
- },
- }
-
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, request.TargetId, args...)
-}
-
-// DownloadImageToOnuDevice invokes download image rpc
-func (ap *AdapterProxy) DownloadImageToOnuDevice(ctx context.Context, device *voltha.Device, downloadRequest *voltha.DeviceImageDownloadRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "download-image-to-device", log.Fields{"device-id": device.Id, "image": downloadRequest.Image.Name})
- rpc := "Download_onu_image"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceImageDownloadReq", Value: downloadRequest},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) GetOnuImageStatus(ctx context.Context, device *voltha.Device, request *voltha.DeviceImageRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "get-image-status", log.Fields{"device-id": device.Id})
- rpc := "Get_onu_image_status"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceImageReq", Value: request},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) ActivateOnuImage(ctx context.Context, device *voltha.Device, request *voltha.DeviceImageRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "activate-onu-image", log.Fields{"device-id": device.Id})
- rpc := "Activate_onu_image"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceImageReq", Value: request},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) AbortImageUpgrade(ctx context.Context, device *voltha.Device, request *voltha.DeviceImageRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "abort-image-upgrade", log.Fields{"device-id": device.Id})
- rpc := "Abort_onu_image_upgrade"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceImageReq", Value: request},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) CommitImage(ctx context.Context, device *voltha.Device, request *voltha.DeviceImageRequest) (chan *kafka.RpcResponse, error) {
- logger.Debugw(ctx, "commit-image", log.Fields{"device-id": device.Id})
- rpc := "Commit_onu_image"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceImageReq", Value: request},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
-
-func (ap *AdapterProxy) GetOnuImages(ctx context.Context, device *voltha.Device, id *common.ID) (chan *kafka.RpcResponse, error) {
- logger.Debug(ctx, "get-onu-images")
- rpc := "Get_onu_images"
- toTopic, err := ap.getAdapterTopic(ctx, device.Id, device.Adapter)
- if err != nil {
- return nil, err
- }
- args := []*kafka.KVArg{
- {Key: "deviceId", Value: &ic.StrType{Val: id.Id}},
- }
- replyToTopic := ap.getCoreTopic()
- return ap.sendRPC(ctx, rpc, toTopic, &replyToTopic, true, device.Id, args...)
-}
diff --git a/rw_core/core/device/remote/adapter_proxy_test.go b/rw_core/core/device/remote/adapter_proxy_test.go
deleted file mode 100755
index ad8cd31..0000000
--- a/rw_core/core/device/remote/adapter_proxy_test.go
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package remote
-
-import (
- "context"
- "crypto/rand"
- "strings"
- "testing"
- "time"
-
- "github.com/golang/protobuf/ptypes"
- any2 "github.com/golang/protobuf/ptypes/any"
- cm "github.com/opencord/voltha-go/rw_core/mocks"
- com "github.com/opencord/voltha-lib-go/v5/pkg/adapters/common"
- "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- mock_kafka "github.com/opencord/voltha-lib-go/v5/pkg/mocks/kafka"
- ic "github.com/opencord/voltha-protos/v4/go/inter_container"
- of "github.com/opencord/voltha-protos/v4/go/openflow_13"
- "github.com/opencord/voltha-protos/v4/go/voltha"
- "github.com/stretchr/testify/assert"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
-)
-
-const (
- coreName = "rw_core"
- adapterName = "adapter_mock"
- coreInstanceID = "1000"
-)
-
-var (
- coreKafkaICProxy kafka.InterContainerProxy
- adapterKafkaICProxy kafka.InterContainerProxy
- kc kafka.Client
- adapterReqHandler *com.RequestHandlerProxy
- adapter *cm.Adapter
-)
-
-func init() {
- ctx := context.Background()
- if _, err := log.SetDefaultLogger(log.JSON, 0, log.Fields{"instanceId": coreInstanceID}); err != nil {
- logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
- }
- // Set the log level to Warning
- log.SetAllLogLevel(log.WarnLevel)
-
- var err error
-
- // Create the KV client
- kc = mock_kafka.NewKafkaClient()
-
- // Setup core inter-container proxy and core request handler
- coreKafkaICProxy = kafka.NewInterContainerProxy(
- kafka.MsgClient(kc),
- kafka.DefaultTopic(&kafka.Topic{Name: coreName}))
-
- if err = coreKafkaICProxy.Start(ctx); err != nil {
- logger.Fatalw(ctx, "Failure-starting-core-kafka-intercontainerProxy", log.Fields{"error": err})
- }
- if err = coreKafkaICProxy.SubscribeWithDefaultRequestHandler(ctx, kafka.Topic{Name: coreName}, 0); err != nil {
- logger.Fatalw(ctx, "Failure-subscribing-core-request-handler", log.Fields{"error": err})
- }
-
- // Setup adapter inter-container proxy and adapter request handler
- adapterCoreProxy := com.NewCoreProxy(ctx, nil, adapterName, coreName)
- adapter = cm.NewAdapter(adapterCoreProxy)
- adapterReqHandler = com.NewRequestHandlerProxy(coreInstanceID, adapter, adapterCoreProxy)
- adapterKafkaICProxy = kafka.NewInterContainerProxy(
- kafka.MsgClient(kc),
- kafka.DefaultTopic(&kafka.Topic{Name: adapterName}),
- kafka.RequestHandlerInterface(adapterReqHandler))
-
- if err = adapterKafkaICProxy.Start(ctx); err != nil {
- logger.Fatalw(ctx, "Failure-starting-adapter-kafka-intercontainerProxy", log.Fields{"error": err})
- }
- if err = adapterKafkaICProxy.SubscribeWithDefaultRequestHandler(ctx, kafka.Topic{Name: adapterName}, 0); err != nil {
- logger.Fatalw(ctx, "Failure-subscribing-adapter-request-handler", log.Fields{"error": err})
- }
-}
-
-func getRandomBytes(size int) (bytes []byte, err error) {
- bytes = make([]byte, size)
- _, err = rand.Read(bytes)
- return
-}
-
-func TestCreateAdapterProxy(t *testing.T) {
- ap := NewAdapterProxy(coreKafkaICProxy, coreName, mock_kafka.NewEndpointManager())
- assert.NotNil(t, ap)
-}
-
-func waitForResponse(ctx context.Context, ch chan *kafka.RpcResponse) (*any2.Any, error) {
- select {
- case rpcResponse, ok := <-ch:
- if !ok {
- return nil, status.Error(codes.Aborted, "channel-closed")
- } else if rpcResponse.Err != nil {
- return nil, rpcResponse.Err
- } else {
- return rpcResponse.Reply, nil
- }
- case <-ctx.Done():
- return nil, ctx.Err()
- }
-}
-
-func testSimpleRequests(t *testing.T) {
- type simpleRequest func(context.Context, *voltha.Device) (chan *kafka.RpcResponse, error)
- ap := NewAdapterProxy(coreKafkaICProxy, coreName, mock_kafka.NewEndpointManager())
- simpleRequests := []simpleRequest{
- ap.AdoptDevice,
- ap.DisableDevice,
- ap.RebootDevice,
- ap.DeleteDevice,
- ap.ReconcileDevice,
- ap.ReEnableDevice,
- }
- for _, f := range simpleRequests {
- // Success
- d := &voltha.Device{Id: "deviceId", Adapter: adapterName}
- ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
- rpcResponse, err := f(ctx, d)
- assert.Nil(t, err)
- _, err = waitForResponse(ctx, rpcResponse)
- assert.Nil(t, err)
- cancel()
-
- // Failure - invalid adapter
- expectedError := "context deadline exceeded"
- d = &voltha.Device{Id: "deviceId", Adapter: "adapter_mock_1"}
- ctx, cancel = context.WithTimeout(context.Background(), 20*time.Millisecond)
- rpcResponse, err = f(ctx, d)
- assert.Nil(t, err)
- _, err = waitForResponse(ctx, rpcResponse)
- cancel()
- assert.NotNil(t, err)
- assert.True(t, strings.Contains(err.Error(), expectedError))
-
- // Failure - timeout
- d = &voltha.Device{Id: "deviceId", Adapter: adapterName}
- ctx, cancel = context.WithTimeout(context.Background(), 100*time.Nanosecond)
- rpcResponse, err = f(ctx, d)
- assert.Nil(t, err)
- _, err = waitForResponse(ctx, rpcResponse)
- cancel()
- assert.NotNil(t, err)
- assert.True(t, strings.Contains(err.Error(), expectedError))
- }
-}
-
-func testGetSwitchCapabilityFromAdapter(t *testing.T) {
- ap := NewAdapterProxy(coreKafkaICProxy, coreName, mock_kafka.NewEndpointManager())
- d := &voltha.Device{Id: "deviceId", Adapter: adapterName}
- ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
- defer cancel()
- rpcResponse, err := ap.GetOfpDeviceInfo(ctx, d)
- assert.Nil(t, err)
- response, err := waitForResponse(ctx, rpcResponse)
- assert.Nil(t, err)
- switchCap := &ic.SwitchCapability{}
- err = ptypes.UnmarshalAny(response, switchCap)
- assert.Nil(t, err)
- assert.NotNil(t, switchCap)
- expectedCap, _ := adapter.Get_ofp_device_info(ctx, d)
- assert.Equal(t, switchCap.String(), expectedCap.String())
-}
-
-func testPacketOut(t *testing.T) {
- ap := NewAdapterProxy(coreKafkaICProxy, coreName, mock_kafka.NewEndpointManager())
- d := &voltha.Device{Id: "deviceId", Adapter: adapterName}
- outPort := uint32(1)
- packet, err := getRandomBytes(50)
- assert.Nil(t, err)
- ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
- defer cancel()
- rpcResponse, err := ap.PacketOut(ctx, adapterName, d.Id, outPort, &of.OfpPacketOut{Data: packet})
- assert.Nil(t, err)
- _, err = waitForResponse(ctx, rpcResponse)
- assert.Nil(t, err)
-}
-
-func testFlowUpdates(t *testing.T) {
- ap := NewAdapterProxy(coreKafkaICProxy, coreName, mock_kafka.NewEndpointManager())
- d := &voltha.Device{Id: "deviceId", Adapter: adapterName}
- _, err := ap.UpdateFlowsBulk(context.Background(), d, nil, nil, &voltha.FlowMetadata{})
- assert.Nil(t, err)
- flowChanges := &voltha.FlowChanges{ToAdd: &voltha.Flows{Items: nil}, ToRemove: &voltha.Flows{Items: nil}}
- groupChanges := &voltha.FlowGroupChanges{ToAdd: &voltha.FlowGroups{Items: nil}, ToRemove: &voltha.FlowGroups{Items: nil}, ToUpdate: &voltha.FlowGroups{Items: nil}}
- ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
- defer cancel()
- rpcResponse, err := ap.UpdateFlowsIncremental(ctx, d, flowChanges, groupChanges, &voltha.FlowMetadata{})
- assert.Nil(t, err)
- _, err = waitForResponse(ctx, rpcResponse)
- assert.Nil(t, err)
-}
-
-func testPmUpdates(t *testing.T) {
- ap := NewAdapterProxy(coreKafkaICProxy, coreName, mock_kafka.NewEndpointManager())
- d := &voltha.Device{Id: "deviceId", Adapter: adapterName}
- ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
- defer cancel()
- rpcResponse, err := ap.UpdatePmConfigs(ctx, d, &voltha.PmConfigs{})
- assert.Nil(t, err)
- _, err = waitForResponse(ctx, rpcResponse)
- assert.Nil(t, err)
-}
-
-func TestSuiteAdapterProxy(t *testing.T) {
- //1. Test the simple requests first
- testSimpleRequests(t)
-
- //2. Test get switch capability
- testGetSwitchCapabilityFromAdapter(t)
-
- //3. Test PacketOut
- testPacketOut(t)
-
- //4. Test flow updates
- testFlowUpdates(t)
-
- //5. Pm configs
- testPmUpdates(t)
-}
diff --git a/rw_core/core/device/remote/common.go b/rw_core/core/device/remote/common.go
deleted file mode 100644
index 2e44b29..0000000
--- a/rw_core/core/device/remote/common.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// Package core Common Logger initialization
-package remote
-
-import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
-)
-
-var logger log.CLogger
-
-func init() {
- // Setup this package so that it's log level can be modified at run time
- var err error
- logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{})
- if err != nil {
- panic(err)
- }
-}
diff --git a/rw_core/core/device/state/common.go b/rw_core/core/device/state/common.go
index 346841a..43d6419 100644
--- a/rw_core/core/device/state/common.go
+++ b/rw_core/core/device/state/common.go
@@ -18,7 +18,7 @@
package state
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/state/transitions.go b/rw_core/core/device/state/transitions.go
index c3b98e7..80ac28e 100644
--- a/rw_core/core/device/state/transitions.go
+++ b/rw_core/core/device/state/transitions.go
@@ -18,10 +18,12 @@
import (
"context"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
"reflect"
"runtime"
+
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/core"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
)
// deviceType mentions type of device like parent, child
@@ -68,7 +70,7 @@
Admin voltha.AdminState_Types
Connection voltha.ConnectStatus_Types
Operational voltha.OperStatus_Types
- Transient voltha.DeviceTransientState_Types
+ Transient core.DeviceTransientState_Types
}
// transitionHandler function type which takes the current and previous device info as input parameter
@@ -112,242 +114,242 @@
transitionMap.transitions,
transition{
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.SetupUNILogicalPorts}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.SetupUNILogicalPorts}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ //DELETE PRE PROVISIONED State device forcefully
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_FORCE_DELETING},
+ previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_FORCE_DELETING},
handlers: []transitionHandler{dMgr.RunPostDeviceDelete}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ // DELETE PRE PROVISIONED State device no force option set
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
+ previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
handlers: []transitionHandler{dMgr.RunPostDeviceDelete}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ //DELETE device forcefully
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_FORCE_DELETING},
+ previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_FORCE_DELETING},
handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ //DELETE device after adapter response
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
+ previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ //DELETE no operation transition
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_FROM_ADAPTER},
+ previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_DELETING_FROM_ADAPTER},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.DeleteAllDeviceFlows}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.DeleteAllDeviceFlows}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ //DELETE force case
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_FORCE_DELETING},
+ previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_FORCE_DELETING},
handlers: []transitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ //DELETE after adapter response case
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
+ previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
handlers: []transitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
transitionMap.transitions = append(transitionMap.transitions,
transition{ //DELETE wait for adapter response(no operation)
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_FROM_ADAPTER},
+ previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_ANY},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_DELETING_FROM_ADAPTER},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: parent,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: child,
- previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
- currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
+ previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
+ currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_NONE},
handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{dMgr.ReconcilingCleanup}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{dMgr.ReconcilingCleanup}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{dMgr.ReconcilingCleanup}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{dMgr.ReconcilingCleanup}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING_FAILED, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING_FAILED, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{dMgr.ReconcilingCleanup}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING_FAILED, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING_FAILED, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{dMgr.ReconcilingCleanup}})
transitionMap.transitions = append(transitionMap.transitions,
transition{
deviceType: any,
- previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
- currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING_FAILED, Transient: voltha.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
+ currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_RECONCILING_FAILED, Transient: core.DeviceTransientState_RECONCILE_IN_PROGRESS},
handlers: []transitionHandler{dMgr.ReconcilingCleanup}})
return &transitionMap
}
-func getDeviceStates(device *voltha.Device, transientState voltha.DeviceTransientState_Types) deviceState {
+func getDeviceStates(device *voltha.Device, transientState core.DeviceTransientState_Types) deviceState {
return deviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus,
Transient: transientState}
}
@@ -362,14 +364,14 @@
transient: currPrevStateMatch}
}
// Do we have transient state match?
- if current.Transient == transition.currentState.Transient && transition.currentState.Transient != voltha.DeviceTransientState_ANY {
- if previous.Transient == transition.previousState.Transient || transition.previousState.Transient == voltha.DeviceTransientState_ANY {
+ if current.Transient == transition.currentState.Transient && transition.currentState.Transient != core.DeviceTransientState_ANY {
+ if previous.Transient == transition.previousState.Transient || transition.previousState.Transient == core.DeviceTransientState_ANY {
m.transient = currPrevStateMatch
} else {
m.transient = currStateOnlyMatch
}
- } else if current.Transient == transition.currentState.Transient && transition.currentState.Transient == voltha.DeviceTransientState_ANY {
- if previous.Transient == transition.previousState.Transient || transition.previousState.Transient == voltha.DeviceTransientState_ANY {
+ } else if current.Transient == transition.currentState.Transient && transition.currentState.Transient == core.DeviceTransientState_ANY {
+ if previous.Transient == transition.previousState.Transient || transition.previousState.Transient == core.DeviceTransientState_ANY {
m.transient = currWildcardMatch
}
}
@@ -426,7 +428,7 @@
// getTransitionHandler returns transition handler & a flag that's set if the transition is invalid
func (tMap *TransitionMap) getTransitionHandler(ctx context.Context, cDevice, pDevice *voltha.Device,
- cTransientState, pTransientState voltha.DeviceTransientState_Types) []transitionHandler {
+ cTransientState, pTransientState core.DeviceTransientState_Types) []transitionHandler {
//1. Get the previous and current set of states
cState := getDeviceStates(cDevice, cTransientState)
pState := getDeviceStates(pDevice, pTransientState)
@@ -468,7 +470,7 @@
}
func (tMap *TransitionMap) ProcessTransition(ctx context.Context, device, prevDevice *voltha.Device,
- deviceTransientState, prevDeviceTransientState voltha.DeviceTransientState_Types) error {
+ deviceTransientState, prevDeviceTransientState core.DeviceTransientState_Types) error {
// This will be triggered on every state update
logger.Debugw(ctx, "state-transition", log.Fields{
"device": device.Id,
diff --git a/rw_core/core/device/state/transitions_test.go b/rw_core/core/device/state/transitions_test.go
index ad53526..5065a60 100644
--- a/rw_core/core/device/state/transitions_test.go
+++ b/rw_core/core/device/state/transitions_test.go
@@ -21,7 +21,9 @@
"reflect"
"testing"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-protos/v5/go/core"
+
+ "github.com/opencord/voltha-protos/v5/go/voltha"
"github.com/stretchr/testify/assert"
)
@@ -52,13 +54,13 @@
}
func assertInvalidTransition(t *testing.T, device, prevDevice *voltha.Device) {
- handlers := transitionMap.getTransitionHandler(context.Background(), device, prevDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers := transitionMap.getTransitionHandler(context.Background(), device, prevDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.NotifyInvalidTransition).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
}
-func assertNoOpTransition(t *testing.T, device, prevDevice *voltha.Device, transientState voltha.DeviceTransientState_Types) {
+func assertNoOpTransition(t *testing.T, device, prevDevice *voltha.Device, transientState core.DeviceTransientState_Types) {
handlers := transitionMap.getTransitionHandler(context.Background(), device, prevDevice, transientState,
transientState)
assert.Equal(t, 0, len(handlers))
@@ -69,134 +71,134 @@
previousDevice := getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVATING)
device := getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVE)
- handlers := transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers := transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.CreateLogicalDevice).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVATING)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.CreateLogicalDevice).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVATING)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.CreateLogicalDevice).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVATING)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.CreateLogicalDevice).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVATING)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.CreateLogicalDevice).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_DISCOVERED)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_DISCOVERED)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_DISCOVERED)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_DISCOVERED)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVATING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVATING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVATING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVATING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.SetupUNILogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_FORCE_DELETING,
- voltha.DeviceTransientState_ANY)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_FORCE_DELETING,
+ core.DeviceTransientState_ANY)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE,
- voltha.DeviceTransientState_ANY)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE,
+ core.DeviceTransientState_ANY)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
device = getDevice(false, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_FORCE_DELETING,
- voltha.DeviceTransientState_ANY)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_FORCE_DELETING,
+ core.DeviceTransientState_ANY)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVE)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_FAILED)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_FORCE_DELETING,
- voltha.DeviceTransientState_ANY)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_FORCE_DELETING,
+ core.DeviceTransientState_ANY)
assert.Equal(t, 3, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ChildDeviceLost).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
assert.True(t, reflect.ValueOf(tdm.DeleteLogicalPorts).Pointer() == reflect.ValueOf(handlers[1]).Pointer())
@@ -204,8 +206,8 @@
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 4, len(handlers))
assert.True(t, reflect.ValueOf(tdm.DeleteAllLogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
assert.True(t, reflect.ValueOf(tdm.DeleteAllChildDevices).Pointer() == reflect.ValueOf(handlers[1]).Pointer())
@@ -214,15 +216,15 @@
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.CreateLogicalDevice).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 4, len(handlers))
assert.True(t, reflect.ValueOf(tdm.DeleteAllLogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
assert.True(t, reflect.ValueOf(tdm.DeleteAllChildDevices).Pointer() == reflect.ValueOf(handlers[1]).Pointer())
@@ -231,78 +233,78 @@
previousDevice = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_NONE,
- voltha.DeviceTransientState_NONE)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_NONE,
+ core.DeviceTransientState_NONE)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.CreateLogicalDevice).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING_FAILED)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING_FAILED)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING_FAILED)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING_FAILED)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_RECONCILING_FAILED)
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS,
- voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS,
+ core.DeviceTransientState_RECONCILE_IN_PROGRESS)
assert.Equal(t, 1, len(handlers))
assert.True(t, reflect.ValueOf(tdm.ReconcilingCleanup).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
@@ -344,8 +346,8 @@
for _, device := range deleteDeviceTest.devices {
device.Root = true
t.Run(testName, func(t *testing.T) {
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_FORCE_DELETING,
- voltha.DeviceTransientState_ANY)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_FORCE_DELETING,
+ core.DeviceTransientState_ANY)
assert.Equal(t, 4, len(handlers))
for idx, expHandler := range deleteDeviceTest.expectedParentHandlers {
assert.True(t, reflect.ValueOf(expHandler).Pointer() == reflect.ValueOf(handlers[idx]).Pointer())
@@ -359,8 +361,8 @@
for _, device := range deleteDeviceTest.devices {
device.Root = false
t.Run(testName, func(t *testing.T) {
- handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, voltha.DeviceTransientState_FORCE_DELETING,
- voltha.DeviceTransientState_ANY)
+ handlers = transitionMap.getTransitionHandler(ctx, device, previousDevice, core.DeviceTransientState_FORCE_DELETING,
+ core.DeviceTransientState_ANY)
assert.Equal(t, 3, len(handlers))
for idx, expHandler := range deleteDeviceTest.expectedChildHandlers {
assert.True(t, reflect.ValueOf(expHandler).Pointer() == reflect.ValueOf(handlers[idx]).Pointer())
@@ -397,71 +399,71 @@
previousDevice := getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
device := getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(true, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
device = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(false, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVATING)
device = getDevice(false, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_DISCOVERED)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(false, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_DISCOVERED)
device = getDevice(false, voltha.AdminState_PREPROVISIONED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(false, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(false, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_NONE)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_NONE)
previousDevice = getDevice(true, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
device = getDevice(true, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(true, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
device = getDevice(true, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(false, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
device = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
device = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(false, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
device = getDevice(false, voltha.AdminState_DOWNLOADING_IMAGE, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
previousDevice = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_ACTIVATING)
device = getDevice(true, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_RECONCILING)
- assertNoOpTransition(t, device, previousDevice, voltha.DeviceTransientState_RECONCILE_IN_PROGRESS)
+ assertNoOpTransition(t, device, previousDevice, core.DeviceTransientState_RECONCILE_IN_PROGRESS)
}
func TestMatch(t *testing.T) {
diff --git a/rw_core/core/device/transientstate/common.go b/rw_core/core/device/transientstate/common.go
index feabb19..920c567 100644
--- a/rw_core/core/device/transientstate/common.go
+++ b/rw_core/core/device/transientstate/common.go
@@ -18,7 +18,7 @@
package transientstate
import (
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
)
var logger log.CLogger
diff --git a/rw_core/core/device/transientstate/loader.go b/rw_core/core/device/transientstate/loader.go
index 9a95bd9..e953b91 100644
--- a/rw_core/core/device/transientstate/loader.go
+++ b/rw_core/core/device/transientstate/loader.go
@@ -21,9 +21,10 @@
"fmt"
"sync"
+ "github.com/opencord/voltha-protos/v5/go/core"
+
"github.com/opencord/voltha-go/db/model"
- "github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -37,7 +38,7 @@
}
type data struct {
- transientState voltha.DeviceTransientState_Types
+ transientState core.DeviceTransientState_Types
deviceID string
}
@@ -45,7 +46,7 @@
return &Loader{
dbProxy: dbProxy,
deviceTransientState: &data{
- transientState: voltha.DeviceTransientState_NONE,
+ transientState: core.DeviceTransientState_NONE,
deviceID: deviceID,
},
}
@@ -57,7 +58,7 @@
loader.lock.Lock()
defer loader.lock.Unlock()
- var deviceTransientState voltha.DeviceTransientState
+ var deviceTransientState core.DeviceTransientState
have, err := loader.dbProxy.Get(ctx, loader.deviceTransientState.deviceID, &deviceTransientState)
if err != nil {
logger.Errorw(ctx, "failed-to-get-device-transient-state-from-cluster-data-proxy", log.Fields{"error": err})
@@ -67,7 +68,7 @@
loader.deviceTransientState.transientState = deviceTransientState.TransientState
return
}
- loader.deviceTransientState.transientState = voltha.DeviceTransientState_NONE
+ loader.deviceTransientState.transientState = core.DeviceTransientState_NONE
}
// Lock acquires the lock for deviceTransientStateLoader, and returns a handle
@@ -88,14 +89,14 @@
}
// GetReadOnly returns device transient which MUST NOT be modified externally, but which is safe to keep indefinitely
-func (h *Handle) GetReadOnly() voltha.DeviceTransientState_Types {
+func (h *Handle) GetReadOnly() core.DeviceTransientState_Types {
return h.data.transientState
}
// Update updates device transient state in KV store
// The provided device transient state must not be modified afterwards.
-func (h *Handle) Update(ctx context.Context, state voltha.DeviceTransientState_Types) error {
- var tState voltha.DeviceTransientState
+func (h *Handle) Update(ctx context.Context, state core.DeviceTransientState_Types) error {
+ var tState core.DeviceTransientState
tState.TransientState = state
if err := h.loader.dbProxy.Set(ctx, fmt.Sprint(h.data.deviceID), &tState); err != nil {
return status.Errorf(codes.Internal, "failed-to-update-device-%v-transient-state: %s", h.data.deviceID, err)