[VOL-1614] Device Management update in the Core
This commit went over the device management of devices in the Core
and made the following changes:
1) Update the device state machine to not remove logical
device or ports when a device is disabled.
2) Fix some issues around device deletion
3) Add additional APIs between the Core and Adapters to handle
the scenarios of enable/disable/delete a device
4) Update the simulated Adapters to handle disable/reenable/delete
5) Add a new set of tests for teh device state machine.
Change-Id: Ib2be87ec011762d5315a6d54581a87c1891e92be
diff --git a/adapters/common/core_proxy.go b/adapters/common/core_proxy.go
index 5bbd176..e1a7e34 100644
--- a/adapters/common/core_proxy.go
+++ b/adapters/common/core_proxy.go
@@ -178,6 +178,27 @@
return unPackResponse(rpc, deviceId, success, result)
}
+func (ap *CoreProxy) DeleteAllPorts(ctx context.Context, deviceId string) error {
+ log.Debugw("DeleteAllPorts", log.Fields{"deviceId": deviceId})
+ rpc := "DeleteAllPorts"
+ // Use a device specific topic to send the request. The adapter handling the device creates a device
+ // specific topic
+ toTopic := ap.getCoreTopic(deviceId)
+ args := make([]*kafka.KVArg, 2)
+ id := &voltha.ID{Id: deviceId}
+
+ args[0] = &kafka.KVArg{
+ Key: "device_id",
+ Value: id,
+ }
+
+ // Use a device specific topic as we are the only adaptercore handling requests for this device
+ replyToTopic := ap.getAdapterTopic()
+ success, result := ap.kafkaICProxy.InvokeRPC(nil, rpc, &toTopic, &replyToTopic, true, deviceId, args...)
+ log.Debugw("DeleteAllPorts-response", log.Fields{"deviceId": deviceId, "success": success})
+ return unPackResponse(rpc, deviceId, success, result)
+}
+
func (ap *CoreProxy) DeviceStateUpdate(ctx context.Context, deviceId string,
connStatus voltha.ConnectStatus_ConnectStatus, operStatus voltha.OperStatus_OperStatus) error {
log.Debugw("DeviceStateUpdate", log.Fields{"deviceId": deviceId})
@@ -211,7 +232,7 @@
func (ap *CoreProxy) ChildDeviceDetected(ctx context.Context, parentDeviceId string, parentPortNo int,
childDeviceType string, channelId int, vendorId string, serialNumber string, onuId int64) error {
- log.Debugw("ChildDeviceDetected", log.Fields{"pPeviceId": parentDeviceId, "channelId": channelId})
+ log.Debugw("ChildDeviceDetected", log.Fields{"pDeviceId": parentDeviceId, "channelId": channelId})
rpc := "ChildDeviceDetected"
// Use a device specific topic to send the request. The adapter handling the device creates a device
// specific topic
@@ -261,6 +282,46 @@
}
+func (ap *CoreProxy) ChildDevicesLost(ctx context.Context, parentDeviceId string) error {
+ log.Debugw("ChildDevicesLost", log.Fields{"pDeviceId": parentDeviceId})
+ rpc := "ChildDevicesLost"
+ // Use a device specific topic to send the request. The adapter handling the device creates a device
+ // specific topic
+ toTopic := ap.getCoreTopic(parentDeviceId)
+ replyToTopic := ap.getAdapterTopic()
+
+ args := make([]*kafka.KVArg, 1)
+ id := &voltha.ID{Id: parentDeviceId}
+ args[0] = &kafka.KVArg{
+ Key: "parent_device_id",
+ Value: id,
+ }
+
+ success, result := ap.kafkaICProxy.InvokeRPC(nil, rpc, &toTopic, &replyToTopic, true, parentDeviceId, args...)
+ log.Debugw("ChildDevicesLost-response", log.Fields{"pDeviceId": parentDeviceId, "success": success})
+ return unPackResponse(rpc, parentDeviceId, success, result)
+}
+
+func (ap *CoreProxy) ChildDevicesDetected(ctx context.Context, parentDeviceId string) error {
+ log.Debugw("ChildDevicesDetected", log.Fields{"pDeviceId": parentDeviceId})
+ rpc := "ChildDevicesDetected"
+ // Use a device specific topic to send the request. The adapter handling the device creates a device
+ // specific topic
+ toTopic := ap.getCoreTopic(parentDeviceId)
+ replyToTopic := ap.getAdapterTopic()
+
+ args := make([]*kafka.KVArg, 1)
+ id := &voltha.ID{Id: parentDeviceId}
+ args[0] = &kafka.KVArg{
+ Key: "parent_device_id",
+ Value: id,
+ }
+
+ success, result := ap.kafkaICProxy.InvokeRPC(nil, rpc, &toTopic, &replyToTopic, true, parentDeviceId, args...)
+ log.Debugw("ChildDevicesDetected-response", log.Fields{"pDeviceId": parentDeviceId, "success": success})
+ return unPackResponse(rpc, parentDeviceId, success, result)
+}
+
func (ap *CoreProxy) GetDevice(ctx context.Context, parentDeviceId string, deviceId string) (*voltha.Device, error) {
log.Debugw("GetDevice", log.Fields{"deviceId": deviceId})
rpc := "GetDevice"
diff --git a/adapters/common/request_handler.go b/adapters/common/request_handler.go
index 8b582b8..e0c7860 100644
--- a/adapters/common/request_handler.go
+++ b/adapters/common/request_handler.go
@@ -191,6 +191,40 @@
}
func (rhp *RequestHandlerProxy) Delete_device(args []*ic.Argument) (*empty.Empty, error) {
+ if len(args) < 3 {
+ log.Warn("invalid-number-of-args", log.Fields{"args": args})
+ err := errors.New("invalid-number-of-args")
+ return nil, err
+ }
+
+ device := &voltha.Device{}
+ transactionID := &ic.StrType{}
+ fromTopic := &ic.StrType{}
+ for _, arg := range args {
+ switch arg.Key {
+ case "device":
+ if err := ptypes.UnmarshalAny(arg.Value, device); err != nil {
+ log.Warnw("cannot-unmarshal-device", log.Fields{"error": err})
+ return nil, err
+ }
+ case kafka.TransactionKey:
+ if err := ptypes.UnmarshalAny(arg.Value, transactionID); err != nil {
+ log.Warnw("cannot-unmarshal-transaction-ID", log.Fields{"error": err})
+ return nil, err
+ }
+ case kafka.FromTopic:
+ if err := ptypes.UnmarshalAny(arg.Value, fromTopic); err != nil {
+ log.Warnw("cannot-unmarshal-from-topic", log.Fields{"error": err})
+ return nil, err
+ }
+ }
+ }
+ //Update the core reference for that device
+ rhp.coreProxy.UpdateCoreReference(device.Id, fromTopic.Val)
+ //Invoke the Disable_device API on the adapter
+ if err := rhp.adapter.Delete_device(device); err != nil {
+ return nil, status.Errorf(codes.NotFound, "%s", err.Error())
+ }
return new(empty.Empty), nil
}
diff --git a/adapters/iAdapter.go b/adapters/iAdapter.go
index a1dfa16..017082d 100644
--- a/adapters/iAdapter.go
+++ b/adapters/iAdapter.go
@@ -33,7 +33,7 @@
Reenable_device(device *voltha.Device) error
Reboot_device(device *voltha.Device) error
Self_test_device(device *voltha.Device) error
- Gelete_device(device *voltha.Device) error
+ Delete_device(device *voltha.Device) error
Get_device_details(device *voltha.Device) error
Update_flows_bulk(device *voltha.Device, flows *voltha.Flows, groups *voltha.FlowGroups) error
Update_flows_incrementally(device *voltha.Device, flows *openflow_13.FlowChanges, groups *openflow_13.FlowGroupChanges) error
diff --git a/adapters/simulated_olt/adaptercore/device_handler.go b/adapters/simulated_olt/adaptercore/device_handler.go
index 07f31ff..f64f99b 100644
--- a/adapters/simulated_olt/adaptercore/device_handler.go
+++ b/adapters/simulated_olt/adaptercore/device_handler.go
@@ -218,6 +218,13 @@
log.Errorw("device-state-update-failed", log.Fields{"deviceId": device.Id, "error": err})
return
}
+
+ // Tell the Core that all child devices have been disabled (by default it's an action already taken by the Core
+ if err := dh.coreProxy.ChildDevicesLost(nil, cloned.Id); err != nil {
+ log.Errorw("lost-notif-of-child-devices-failed", log.Fields{"deviceId": device.Id, "error": err})
+ return
+ }
+
log.Debugw("DisableDevice-end", log.Fields{"deviceId": device.Id})
}
@@ -239,5 +246,23 @@
log.Errorw("device-state-update-failed", log.Fields{"deviceId": device.Id, "error": err})
return
}
+
+ // Tell the Core that all child devices have been enabled
+ if err := dh.coreProxy.ChildDevicesDetected(nil, cloned.Id); err != nil {
+ log.Errorw("detection-notif-of-child-devices-failed", log.Fields{"deviceId": device.Id, "error": err})
+ return
+ }
+
log.Debugw("ReEnableDevice-end", log.Fields{"deviceId": device.Id})
}
+
+func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) {
+ cloned := proto.Clone(device).(*voltha.Device)
+ // Update the all ports state on that device to disable
+ if err := dh.coreProxy.DeleteAllPorts(nil, cloned.Id); err != nil {
+ log.Errorw("delete-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
+ return
+ }
+
+ log.Debugw("DeleteDevice-end", log.Fields{"deviceId": device.Id})
+}
diff --git a/adapters/simulated_olt/adaptercore/simulated_olt.go b/adapters/simulated_olt/adaptercore/simulated_olt.go
index fee4dc8..d29fc1e 100644
--- a/adapters/simulated_olt/adaptercore/simulated_olt.go
+++ b/adapters/simulated_olt/adaptercore/simulated_olt.go
@@ -198,8 +198,17 @@
return errors.New("UnImplemented")
}
-func (so *SimulatedOLT) Gelete_device(device *voltha.Device) error {
- return errors.New("UnImplemented")
+func (so *SimulatedOLT) Delete_device(device *voltha.Device) error {
+ if device == nil {
+ log.Warn("device-is-nil")
+ return errors.New("nil-device")
+ }
+ log.Infow("delete-device", log.Fields{"deviceId": device.Id})
+ var handler *DeviceHandler
+ if handler = so.getDeviceHandler(device.Id); handler != nil {
+ go handler.DeleteDevice(device)
+ }
+ return nil
}
func (so *SimulatedOLT) Get_device_details(device *voltha.Device) error {
diff --git a/adapters/simulated_onu/adaptercore/device_handler.go b/adapters/simulated_onu/adaptercore/device_handler.go
index a845427..96cb3d8 100644
--- a/adapters/simulated_onu/adaptercore/device_handler.go
+++ b/adapters/simulated_onu/adaptercore/device_handler.go
@@ -27,6 +27,7 @@
"strconv"
"strings"
"sync"
+ "time"
)
//DeviceHandler follows the same patterns as ponsim_olt. The only difference is that it does not
@@ -105,6 +106,27 @@
log.Errorw("error-updating-device", log.Fields{"deviceId": device.Id, "error": err})
}
+ // Update the device state to DISCOVERED
+ cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
+ cloned.OperStatus = voltha.OperStatus_DISCOVERED
+ if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
+ log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
+ }
+
+ // Sleep to mimic the omci management channel creation with the OLT
+ time.Sleep(10 * time.Millisecond)
+
+ // Update the device state to ACTIVATING
+ cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
+ cloned.OperStatus = voltha.OperStatus_ACTIVATING
+ if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
+ log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
+ }
+
+ // Sleep to mimic the omci discovery ( usually takes a few seconds but for ease of simulated environment we are
+ // setting it to 100ms only.
+ time.Sleep(100 * time.Millisecond)
+
// Use the channel Id, assigned by the parent device to me, as the port number
uni_port := uint32(2)
if device.ProxyAddress != nil {
@@ -223,3 +245,14 @@
}
log.Debugw("ReEnableDevice-end", log.Fields{"deviceId": device.Id})
}
+
+func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) {
+ cloned := proto.Clone(device).(*voltha.Device)
+ // Update the all ports state on that device to disable
+ if err := dh.coreProxy.DeleteAllPorts(nil, cloned.Id); err != nil {
+ log.Errorw("delete-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
+ return
+ }
+
+ log.Debugw("DeleteDevice-end", log.Fields{"deviceId": device.Id})
+}
diff --git a/adapters/simulated_onu/adaptercore/simulated_onu.go b/adapters/simulated_onu/adaptercore/simulated_onu.go
index a74b377..1bdd4bb 100644
--- a/adapters/simulated_onu/adaptercore/simulated_onu.go
+++ b/adapters/simulated_onu/adaptercore/simulated_onu.go
@@ -190,8 +190,17 @@
return errors.New("UnImplemented")
}
-func (so *SimulatedONU) Gelete_device(device *voltha.Device) error {
- return errors.New("UnImplemented")
+func (so *SimulatedONU) Delete_device(device *voltha.Device) error {
+ if device == nil {
+ log.Warn("device-is-nil")
+ return errors.New("nil-device")
+ }
+ log.Infow("delete-device", log.Fields{"deviceId": device.Id})
+ var handler *DeviceHandler
+ if handler = so.getDeviceHandler(device.Id); handler != nil {
+ go handler.DeleteDevice(device)
+ }
+ return nil
}
func (so *SimulatedONU) Get_device_details(device *voltha.Device) error {