[VOL-1385] : Changes to support ONU delete
Tested with,
1. ONU disable->delete
2. ONU delete
3. OLT delete
Change-Id: I8e6ff41a7ea8e94014700f274cb24fea73ac41f4
diff --git a/rw_core/core/adapter_proxy.go b/rw_core/core/adapter_proxy.go
index b7798ad..f6e9867 100755
--- a/rw_core/core/adapter_proxy.go
+++ b/rw_core/core/adapter_proxy.go
@@ -612,3 +612,33 @@
log.Debugw("enablePort-response", log.Fields{"device-id": device.Id, "port-no": port.PortNo, "success": success})
return unPackResponse(rpc, device.Id, success, result)
}
+
+// ChildDeviceLost invokes Child device_lost rpc
+func (ap *AdapterProxy) ChildDeviceLost(ctx context.Context, deviceType string, pDeviceID string, pPortNo uint32, onuID uint32) error {
+ log.Debugw("ChildDeviceLost", log.Fields{"pDeviceId": pDeviceID, "pPortNo": pPortNo, "onuID": onuID})
+ rpc := "child_device_lost"
+ toTopic := ap.getAdapterTopic(deviceType)
+ dID := &ic.StrType{Val: pDeviceID}
+ PortNo := &ic.IntType{Val: int64(pPortNo)}
+ oID := &ic.IntType{Val: int64(onuID)}
+ args := []*kafka.KVArg{
+ {
+ Key: "pDeviceId",
+ Value: dID,
+ },
+ {
+ Key: "pPortNo",
+ Value: PortNo,
+ },
+ {
+ Key: "onuID",
+ Value: oID,
+ }}
+
+ // Use a device specific topic as we are the only core handling requests for this device
+ replyToTopic := ap.getCoreTopic()
+ success, result := ap.kafkaICProxy.InvokeRPC(ctx, rpc, &toTopic, &replyToTopic, true, pDeviceID, args...)
+ log.Debugw("ChildDeviceLost-response", log.Fields{"pDeviceId": pDeviceID, "success": success})
+
+ return unPackResponse(rpc, pDeviceID, success, result)
+}
diff --git a/rw_core/core/device_agent.go b/rw_core/core/device_agent.go
index d20874a..877d991 100755
--- a/rw_core/core/device_agent.go
+++ b/rw_core/core/device_agent.go
@@ -705,35 +705,19 @@
log.Debugw("device-already-in-deleted-state", log.Fields{"id": agent.deviceID})
return nil
}
- if (cloned.AdminState != voltha.AdminState_DISABLED) &&
- (cloned.AdminState != voltha.AdminState_PREPROVISIONED) {
- log.Debugw("device-not-disabled", log.Fields{"id": agent.deviceID})
- //TODO: Needs customized error message
- return status.Errorf(codes.FailedPrecondition, "deviceId:%s, expected-admin-state:%s", agent.deviceID, voltha.AdminState_DISABLED)
- }
if cloned.AdminState != voltha.AdminState_PREPROVISIONED {
- // Send the request to an Adapter only if the device is not in poreporovision state and wait for a response
if err := agent.adapterProxy.DeleteDevice(ctx, cloned); err != nil {
log.Debugw("deleteDevice-error", log.Fields{"id": agent.deviceID, "error": err})
return err
}
}
- // Set the state to deleted after we receive an Ack - this will trigger some background process to clean up
- // the device as well as its association with the logical device
+ //Set the state to deleted - this will trigger some background process to invoke parent adapter to delete child
+ //device and clean up the device as well as its association with the logical device
cloned.AdminState = voltha.AdminState_DELETED
+
if err := agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, ""); err != nil {
return err
}
- // If this is a child device then remove the associated peer ports on the parent device
- if !cloned.Root {
- go func() {
- // since the caller does not wait for this for complete, use background context
- err := agent.deviceMgr.deletePeerPorts(context.Background(), cloned.ParentId, cloned.Id)
- if err != nil {
- log.Errorw("unable-to-delete-peer-ports", log.Fields{"error": err})
- }
- }()
- }
return nil
}
@@ -1296,8 +1280,6 @@
}
func (agent *DeviceAgent) deletePeerPorts(ctx context.Context, deviceID string) error {
- agent.lockDevice.Lock()
- defer agent.lockDevice.Unlock()
log.Debug("deletePeerPorts")
cloned := agent.getDeviceWithoutLock()
@@ -1466,3 +1448,21 @@
}
return nil
}
+
+func (agent *DeviceAgent) ChildDeviceLost(ctx context.Context, device *voltha.Device) error {
+
+ agent.lockDevice.Lock()
+ defer agent.lockDevice.Unlock()
+ log.Debugw("ChildDeviceLost", log.Fields{"id": device.Id})
+
+ //Remove the associated peer ports on the parent device
+ if err := agent.deviceMgr.deletePeerPorts(ctx, device.ParentId, device.Id); err != nil {
+ return err
+ }
+
+ if err := agent.adapterProxy.ChildDeviceLost(ctx, agent.deviceType, agent.deviceID, device.ParentPortNo, device.ProxyAddress.OnuId); err != nil {
+ log.Warnw("ChildDeviceLost-error", log.Fields{"error": err})
+ }
+ return nil
+
+}
diff --git a/rw_core/core/device_manager.go b/rw_core/core/device_manager.go
index df94772..950819e 100755
--- a/rw_core/core/device_manager.go
+++ b/rw_core/core/device_manager.go
@@ -1509,3 +1509,12 @@
sendResponse(ctx, ch, res)
}
+
+// ChildDeviceLost calls parent adapter to delete child device and all its references
+func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, cDevice *voltha.Device) error {
+ log.Debugw("ChildDeviceLost", log.Fields{"deviceid": cDevice.Id})
+ if parentAgent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); parentAgent != nil {
+ return parentAgent.ChildDeviceLost(ctx, cDevice)
+ }
+ return status.Errorf(codes.NotFound, "%s", cDevice.Id)
+}
diff --git a/rw_core/core/device_state_transitions.go b/rw_core/core/device_state_transitions.go
index 7756bf4..0a6264b 100644
--- a/rw_core/core/device_state_transitions.go
+++ b/rw_core/core/device_state_transitions.go
@@ -96,7 +96,13 @@
deviceType: child,
previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
- handlers: []TransitionHandler{dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
+ handlers: []TransitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
+ transitionMap.transitions = append(transitionMap.transitions,
+ Transition{
+ deviceType: child,
+ previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
+ currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
+ handlers: []TransitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
transitionMap.transitions = append(transitionMap.transitions,
Transition{
deviceType: any,
diff --git a/rw_core/core/device_state_transitions_test.go b/rw_core/core/device_state_transitions_test.go
index 7894378..4df728f 100644
--- a/rw_core/core/device_state_transitions_test.go
+++ b/rw_core/core/device_state_transitions_test.go
@@ -199,23 +199,50 @@
from = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
to = getDevice(false, voltha.AdminState_DELETED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
handlers = transitionMap.GetTransitionHandler(from, to)
- assert.Equal(t, 2, len(handlers))
- assert.True(t, reflect.ValueOf(tdm.DeleteLogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
- assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[1]).Pointer())
+ 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())
+ assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[2]).Pointer())
from = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
to = getDevice(false, voltha.AdminState_DELETED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
handlers = transitionMap.GetTransitionHandler(from, to)
- assert.Equal(t, 2, len(handlers))
- assert.True(t, reflect.ValueOf(tdm.DeleteLogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
- assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[1]).Pointer())
+ 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())
+ assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[2]).Pointer())
from = getDevice(false, voltha.AdminState_DISABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVE)
to = getDevice(false, voltha.AdminState_DELETED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_FAILED)
handlers = transitionMap.GetTransitionHandler(from, to)
- assert.Equal(t, 2, len(handlers))
- assert.True(t, reflect.ValueOf(tdm.DeleteLogicalPorts).Pointer() == reflect.ValueOf(handlers[0]).Pointer())
- assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[1]).Pointer())
+ 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())
+ assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[2]).Pointer())
+
+ from = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
+ to = getDevice(false, voltha.AdminState_DELETED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_UNKNOWN)
+ handlers = transitionMap.GetTransitionHandler(from, to)
+ 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())
+ assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[2]).Pointer())
+
+ from = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN)
+ to = getDevice(false, voltha.AdminState_DELETED, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN)
+ handlers = transitionMap.GetTransitionHandler(from, to)
+ 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())
+ assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[2]).Pointer())
+
+ from = getDevice(false, voltha.AdminState_ENABLED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_ACTIVE)
+ to = getDevice(false, voltha.AdminState_DELETED, voltha.ConnectStatus_UNKNOWN, voltha.OperStatus_FAILED)
+ handlers = transitionMap.GetTransitionHandler(from, to)
+ 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())
+ assert.True(t, reflect.ValueOf(tdm.RunPostDeviceDelete).Pointer() == reflect.ValueOf(handlers[2]).Pointer())
}
func TestInvalidTransitions(t *testing.T) {
diff --git a/rw_core/core/grpc_nbi_api_handler_test.go b/rw_core/core/grpc_nbi_api_handler_test.go
index c143f42..b0f0029 100755
--- a/rw_core/core/grpc_nbi_api_handler_test.go
+++ b/rw_core/core/grpc_nbi_api_handler_test.go
@@ -517,6 +517,66 @@
err = waitUntilConditionForLogicalDevices(nb.maxTimeout, nbi, vlFunction)
assert.Nil(t, err)
}
+func (nb *NBTest) testEnableAndDeleteAllDevice(t *testing.T, nbi *APIHandler) {
+ //Create the device with valid data
+ oltDevice, err := nbi.CreateDevice(getContext(), &voltha.Device{Type: nb.oltAdapterName, MacAddress: "aa:bb:cc:cc:ee:ee"})
+ assert.Nil(t, err)
+ assert.NotNil(t, oltDevice)
+
+ //Get an OLT device
+ oltDevice, err = nb.getADevice(true, nbi)
+ assert.Nil(t, err)
+ assert.NotNil(t, oltDevice)
+
+ // Enable the oltDevice
+ _, err = nbi.EnableDevice(getContext(), &voltha.ID{Id: oltDevice.Id})
+ assert.Nil(t, err)
+
+ // Wait for the logical device to be in the ready state
+ var vldFunction isLogicalDeviceConditionSatisfied = func(ld *voltha.LogicalDevice) bool {
+ return ld != nil && len(ld.Ports) == nb.numONUPerOLT+1
+ }
+ err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
+ assert.Nil(t, err)
+
+ //Get all child devices
+ onuDevices, err := nb.core.deviceMgr.getAllChildDevices(getContext(), oltDevice.Id)
+ assert.Nil(t, err)
+
+ // Wait for the all onu devices to be enabled
+ var vdFunction isDeviceConditionSatisfied = func(device *voltha.Device) bool {
+ return device.AdminState == voltha.AdminState_ENABLED
+ }
+ for _, onu := range onuDevices.Items {
+ err = waitUntilDeviceReadiness(onu.Id, nb.maxTimeout, vdFunction, nbi)
+ assert.Nil(t, err)
+ }
+ // Delete the onuDevice
+ for _, onu := range onuDevices.Items {
+ _, err = nbi.DeleteDevice(getContext(), &voltha.ID{Id: onu.Id})
+ assert.Nil(t, err)
+ }
+ // Disable the oltDevice
+ _, err = nbi.DisableDevice(getContext(), &voltha.ID{Id: oltDevice.Id})
+ assert.Nil(t, err)
+
+ // Wait for the olt device to be disabled
+ var vFunction isDeviceConditionSatisfied = func(device *voltha.Device) bool {
+ return device.AdminState == voltha.AdminState_DISABLED && device.OperStatus == voltha.OperStatus_UNKNOWN
+ }
+ err = waitUntilDeviceReadiness(oltDevice.Id, nb.maxTimeout, vFunction, nbi)
+ assert.Nil(t, err)
+
+ // Delete the oltDevice
+ _, err = nbi.DeleteDevice(getContext(), &voltha.ID{Id: oltDevice.Id})
+ assert.Nil(t, err)
+
+ var vFunc isDevicesConditionSatisfied = func(devices *voltha.Devices) bool {
+ return devices != nil && len(devices.Items) == 0
+ }
+ err = waitUntilConditionForDevices(nb.maxTimeout, nbi, vFunc)
+ assert.Nil(t, err)
+}
func (nb *NBTest) testDisableAndEnablePort(t *testing.T, nbi *APIHandler) {
//Get an OLT device
var cp *voltha.Port
@@ -640,6 +700,9 @@
// 6. Test disable and delete all devices
nb.testDisableAndDeleteAllDevice(t, nbi)
+
+ //7. Test enable and delete all devices
+ nb.testEnableAndDeleteAllDevice(t, nbi)
}
//x. TODO - More tests to come
diff --git a/rw_core/coreif/device_manager_if.go b/rw_core/coreif/device_manager_if.go
index b4329be..7a9e64d 100644
--- a/rw_core/coreif/device_manager_if.go
+++ b/rw_core/coreif/device_manager_if.go
@@ -38,4 +38,5 @@
DeleteLogicalPorts(context.Context, *voltha.Device) error
DeleteAllChildDevices(context.Context, *voltha.Device) error
RunPostDeviceDelete(context.Context, *voltha.Device) error
+ ChildDeviceLost(context.Context, *voltha.Device) error
}
diff --git a/rw_core/mocks/adapter_olt.go b/rw_core/mocks/adapter_olt.go
index b9cef0c..2ab98a3 100644
--- a/rw_core/mocks/adapter_olt.go
+++ b/rw_core/mocks/adapter_olt.go
@@ -256,3 +256,8 @@
}()
return nil
}
+
+// Child_device_lost deletes ONU and its references
+func (oltA *OLTAdapter) Child_device_lost(deviceID string, pPortNo uint32, onuID uint32) error { // nolint
+ return nil
+}
diff --git a/rw_core/mocks/device_manager.go b/rw_core/mocks/device_manager.go
index 116c7dc..6edfdc9 100644
--- a/rw_core/mocks/device_manager.go
+++ b/rw_core/mocks/device_manager.go
@@ -176,3 +176,8 @@
func (dm *DeviceManager) ProcessTransition(previous *voltha.Device, current *voltha.Device) error {
return nil
}
+
+// ChildDeviceLost -
+func (dm *DeviceManager) ChildDeviceLost(ctx context.Context, cDevice *voltha.Device) error {
+ return nil
+}