[VOL-2454] Fix for device deletion in the rw_core
When a parent device is deleted, its child devices are deleted
as well. The state machine in the Core ensures this process occurs.
However, there were "duplicate" codes during the parent device
deletion where it was triggering child devices in being deleted
again. This is incorrect is being addressed by this change.
Change-Id: I8dbbe48e97f70638a0ea28444825452b366da137
diff --git a/db/model/persisted_revision.go b/db/model/persisted_revision.go
index b9aad44..e0fcb10 100644
--- a/db/model/persisted_revision.go
+++ b/db/model/persisted_revision.go
@@ -345,24 +345,21 @@
// Drop takes care of eliminating a revision hash that is no longer needed
// and its associated config when required
func (pr *PersistedRevision) StorageDrop(txid string, includeConfig bool) {
- log.Debugw("dropping-revision", log.Fields{"txid": txid, "hash": pr.GetHash(), "config-hash": pr.GetConfig().Hash})
+ log.Debugw("dropping-revision", log.Fields{"txid": txid, "hash": pr.GetHash(), "config-hash": pr.GetConfig().Hash, "key": pr.GetName(), "isStored": pr.isStored})
pr.mutex.Lock()
defer pr.mutex.Unlock()
if pr.kvStore != nil && txid == "" {
- if pr.isStored {
- if pr.isWatched {
- pr.kvStore.DeleteWatch(pr.GetName(), pr.events)
- pr.isWatched = false
- }
-
- if err := pr.kvStore.Delete(pr.GetName()); err != nil {
- log.Errorw("failed-to-remove-revision", log.Fields{"hash": pr.GetHash(), "error": err.Error()})
- } else {
- pr.isStored = false
- }
+ if pr.isWatched {
+ pr.kvStore.DeleteWatch(pr.GetName(), pr.events)
+ pr.isWatched = false
}
+ if err := pr.kvStore.Delete(pr.GetName()); err != nil {
+ log.Errorw("failed-to-remove-revision", log.Fields{"hash": pr.GetHash(), "error": err.Error()})
+ } else {
+ pr.isStored = false
+ }
} else {
if includeConfig {
log.Debugw("attempted-to-remove-transacted-revision-config", log.Fields{"hash": pr.GetConfig().Hash, "txid": txid})
diff --git a/rw_core/core/device_agent.go b/rw_core/core/device_agent.go
index 8cbc63a..d71da27 100755
--- a/rw_core/core/device_agent.go
+++ b/rw_core/core/device_agent.go
@@ -150,7 +150,8 @@
func (agent *DeviceAgent) stop(ctx context.Context) {
agent.lockDevice.Lock()
defer agent.lockDevice.Unlock()
- log.Debug("stopping-device-agent")
+
+ log.Debugw("stopping-device-agent", log.Fields{"deviceId": agent.deviceID, "parentId": agent.parentID})
// First unregister any callbacks
agent.deviceProxy.UnregisterCallback(model.POST_UPDATE, agent.processUpdate)
@@ -165,8 +166,7 @@
log.Debugw("device-already-removed", log.Fields{"id": agent.deviceID})
}
agent.exitChannel <- 1
- log.Debug("device-agent-stopped")
-
+ log.Debugw("device-agent-stopped", log.Fields{"deviceId": agent.deviceID, "parentId": agent.parentID})
}
// Load the most recent state from the KVStore for the device.
diff --git a/rw_core/core/device_manager.go b/rw_core/core/device_manager.go
index 0094264..59cf0a4 100755
--- a/rw_core/core/device_manager.go
+++ b/rw_core/core/device_manager.go
@@ -246,11 +246,7 @@
log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
}
}
- // stop managing the child devices
- childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentID(id)
- for _, cID := range childDeviceIds {
- dMgr.stopManagingDevice(cID)
- }
+ // We do not need to stop the child devices as this is taken care by the state machine.
}
if agent := dMgr.getDeviceAgent(id); agent != nil {
agent.stop(context.TODO())
@@ -1268,10 +1264,9 @@
if err = agent.deleteDevice(context.TODO()); err != nil {
log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
allChildDeleted = false
- } else {
- agent.stop(context.TODO())
- dMgr.deleteDeviceAgentFromMap(agent)
}
+ // 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.
}
}
if !allChildDeleted {
@@ -1280,22 +1275,6 @@
return nil
}
-//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
-// data from the agent instead of using the data from the parent device as that data would disappear from a parent
-// device during a delete device operation.
-func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentID(id string) []string {
- log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
- deviceIds := make([]string, 0)
- dMgr.deviceAgents.Range(func(key, value interface{}) bool {
- agent := value.(*DeviceAgent)
- if agent.parentID == id {
- deviceIds = append(deviceIds, key.(string))
- }
- return true
- })
- return deviceIds
-}
-
//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
diff --git a/rw_core/core/logical_device_agent.go b/rw_core/core/logical_device_agent.go
index 5da6d40..097f9ab 100644
--- a/rw_core/core/logical_device_agent.go
+++ b/rw_core/core/logical_device_agent.go
@@ -111,6 +111,7 @@
ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
ld.Flows = &ofp.Flows{Items: nil}
ld.FlowGroups = &ofp.FlowGroups{Items: nil}
+ ld.Ports = []*voltha.LogicalPort{}
agent.lockLogicalDevice.Lock()
// Save the logical device