VOL-3504 Code changes to support force delete
Change-Id: I041ab2101a607b99e0372e432819a3f10f3a774c
diff --git a/rw_core/core/device/manager.go b/rw_core/core/device/manager.go
index 3899623..9220fe5 100755
--- a/rw_core/core/device/manager.go
+++ b/rw_core/core/device/manager.go
@@ -209,7 +209,6 @@
// DeleteDevice removes a device from the data model
func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
-
logger.Debugw(ctx, "DeleteDevice", log.Fields{"device-id": id.Id})
agent := dMgr.getDeviceAgent(ctx, id.Id)
if agent == nil {
@@ -218,6 +217,17 @@
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) {
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+ logger.Debugw(ctx, "ForceDeleteDevice", 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, "ListDevicePorts", log.Fields{"device-id": deviceID})
@@ -473,10 +483,11 @@
if !device.Root {
continue
}
- if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
+
+ if hostPort != "" && hostPort == device.GetHostAndPort() {
return true, nil
}
- if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
+ if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress {
return true, nil
}
}
@@ -589,8 +600,8 @@
return err
}
- // If the device is in Pre-provisioning or deleted state stop here
- if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
+ // If the device is in Pre-provisioning or getting deleted state stop here
+ if device.AdminState == voltha.AdminState_PREPROVISIONED || dAgent.isDeletionInProgress() {
return nil
}
@@ -645,11 +656,14 @@
}
// isOkToReconcile validates whether a device is in the correct status to be reconciled
-func isOkToReconcile(device *voltha.Device) bool {
+func (dMgr *Manager) isOkToReconcile(ctx context.Context, device *voltha.Device) bool {
if device == nil {
return false
}
- return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
+ if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
+ return device.AdminState != voltha.AdminState_PREPROVISIONED && (!agent.isDeletionInProgress())
+ }
+ return false
}
// adapterRestarted is invoked whenever an adapter is restarted
@@ -672,7 +686,7 @@
continue
}
if isDeviceOwnedByService {
- if isOkToReconcile(rootDevice) {
+ if dMgr.isOkToReconcile(ctx, rootDevice) {
logger.Debugw(ctx, "reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
} else {
@@ -689,7 +703,7 @@
logger.Warnw(ctx, "is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
}
if isDeviceOwnedByService {
- if isOkToReconcile(childDevice) {
+ if dMgr.isOkToReconcile(ctx, childDevice) {
logger.Debugw(ctx, "reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
} else {
@@ -1222,11 +1236,29 @@
//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, "DeleteAllChildDevices")
+ 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 err := agent.deleteDevice(ctx); err != nil {
- logger.Warnw(ctx, "failure-delete-device", log.Fields{"device-id": childDeviceID, "error": err.Error()})
+ 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.