# Managing a device

The first API that a NEM would need to excute to start managing a hardware is the StartManagingDevice.

## StartManagingDevice
![Managing a Device](images/managing_device.png "Start Managing an OLT")
```protobuf
service NativeHWManagementService {
    // Initializes context for a device and sets up required states
    // In the call to StartManagingDevice, the fields of ModifiableComponent which are relevant
    // and their meanings in this context is mentioned below:
    // name = The unique name that needs to be assigned to this hardware;
    // class = COMPONENT_TYPE_UNDEFINED;
    // parent = nil;
    // alias = Optional;
    // asset_id = Optional;
    // uri = IP Address of the Hardware;
    rpc StartManagingDevice(ModifiableComponent) returns(stream StartManagingDeviceResponse);
}
```
The `uri` is what would carry the IP address of the device and the `name` should be something that would uniquely identify the device.

On reception of this rpc, an implementation of Device Manager should validate the IP address and see if it can talk to/setup connection to the device or not. It should setup any required states that might be needed for it's internal implementation.

The NEM would wait for the `StartManagingDeviceResponse` before it will do any futher actions on this device. This response needs to contain the `uuid` assigned to this device. **For futher RPCs it would be the `uuid` that would be used to identify the device.**

*The device manager implementation should ensure that the `uuid` returned is universally unique and* ***does not change across reboots of the device.*** An example could be that the device manager first connects to the device and learns the serial number of the device and then uses this serial number to generate the `uuid` for the device.

## StopManagingDevice
```protobuf
// Stop management of a device and clean up any context caches for that device
rpc StopManagingDevice(StopManagingDeviceRequest) returns(StopManagingDeviceResponse);
```
This RPC is to be used when a device is to be released from the system and no longer needs to be managed.

## GetManagedDevices
```protobuf
// Returns an object containing a list of devices managed by this entity
rpc GetManagedDevices(google.protobuf.Empty) returns(ManagedDevicesResponse);
```
This RPC returns a list of all devices currently managed by the Device Manager.

## GetPhysicalInventory
```protobuf
// Get the HW inventory details of the Device
rpc GetPhysicalInventory(PhysicalInventoryRequest) returns(stream PhysicalInventoryResponse);
```
This RPC is used to retrieve the entire inventory of components of the Hardware. Again the caller has to wait on the response in a stream as implementations of Device Manager could take time to gather all this information.

## GetHWComponentInfo
```protobuf
// Get the details of a particular HW component
rpc GetHWComponentInfo(HWComponentInfoGetRequest) returns(stream HWComponentInfoGetResponse);
```
In the call to this RPC, both the `name` and the `uuid` of the component need to be passed in the `HWComponentInfoGetRequest`.

The `name` has to be unique for each of the components of the hardware and the `uuid` has to be universally unique. Implementation of Device Manager need to ensure this. Both of these two attributes are generated by the Device Manager.

## SetHWComponentInfo
```protobuf
// Sets the permissible attributes of a HW component
rpc SetHWComponentInfo(HWComponentInfoSetRequest) returns(HWComponentInfoSetResponse);
```
In the call to this RPC, both the `name` and the `uuid` of the component need to be passed in the `HWComponentInfoSetRequest`.

Using this RPC, it is possible to modify the `name` of a component, and the Device Manager has to ensure that the name is unique, else it should return an error for this RPC. Although the `name` can be modified, it is recommended that NEM implementations do not do this because Device Managers and take advantage of this and come up with efficient implementations.

## SetLoggingEndpoint
```protobuf
// Sets the location to which logs need to be shipped
rpc SetLoggingEndpoint(SetLoggingEndpointRequest) returns(SetRemoteEndpointResponse);
```
This RPC sets the endpoint where logs from the device should be sent.

## GetLoggingEndpoint
```protobuf
// Gets the configured location to which the logs are being shipped
rpc GetLoggingEndpoint(HardwareID) returns(GetLoggingEndpointResponse);
```
This RPC retrieves the current logging endpoint configuration for a device.

## SetMsgBusEndpoint
```protobuf
// Sets the location of the Message Bus to which events and metrics are shipped
rpc SetMsgBusEndpoint(SetMsgBusEndpointRequest) returns(SetRemoteEndpointResponse);
```
This RPC sets the endpoint for the message bus used for events and metrics.

## GetMsgBusEndpoint
```protobuf
// Gets the configured location to which the events and metrics are being shipped
rpc GetMsgBusEndpoint(google.protobuf.Empty) returns(GetMsgBusEndpointResponse);
```
This RPC retrieves the current message bus endpoint configuration.

## GetLoggableEntities
```protobuf
// Gets the entities of a device on which log can be configured.
rpc GetLoggableEntities(GetLoggableEntitiesRequest) returns(GetLogLevelResponse);
```
This RPC returns the list of entities (e.g., OS, PON Management, etc.) on which log levels can be configured.

## SetLogLevel
```protobuf
// Sets the log level of the device, for each given entity to a certain level.
rpc SetLogLevel(SetLogLevelRequest) returns(SetLogLevelResponse);
```
This RPC sets the log level for one or more entities on a device.

## GetLogLevel
```protobuf
// Gets the configured log level for a certain entity on a certain device.
rpc GetLogLevel(GetLogLevelRequest) returns(GetLogLevelResponse);
```
This RPC retrieves the log level for one or more entities on a device.

## HeartbeatCheck
```protobuf
// Performs the heartbeat check
rpc HeartbeatCheck(google.protobuf.Empty) returns (Heartbeat);
```
This RPC is used to perform the hearbeat check for the connectivity. When the gRPC server streaming is used for conveying the Events and Metrics to external systems, on the connectivity break and reestablishment, the server streaming RPCs need to be established again.

## RebootDevice
```protobuf
// Performs the reboot of the device
rpc RebootDevice(RebootDeviceRequest) returns (RebootDeviceResponse);
```
This RPC is used to administratively reboot the device. The server side implementations should reboot the device only after successfully returning this RPC.

## SetDmLogLevel
```protobuf
// Sets the log level of the Device Manager itself
rpc SetDmLogLevel(SetDmLogLevelRequest) returns(SetDmLogLevelResponse);
```
This RPC sets the log level for the Device Manager process.

## GetDmLogLevel
```protobuf
// Gets the log level at which the Device Manager is running
rpc GetDmLogLevel(GetDmLogLevelRequest) returns(GetDmLogLevelResponse);
```
This RPC retrieves the current log level of the Device Manager process.

---

## EnableHWComponent
```protobuf
// Enables a hardware component on a device.
// At least one of component_name or component_uuid must be provided, along with device_uuid.
rpc EnableHWComponent(EnableHWComponentRequest) returns(EnableHWComponentResponse);
```
This RPC enables a hardware component (such as a port or module) on a managed device.  
You must provide the `device_uuid` and at least one of `component_name` or `component_uuid` in the request.  
If the operation is not supported or the parameters are invalid, an appropriate error will be returned in the response.

## DisableHWComponent
```protobuf
// Disables a hardware component on a device.
// At least one of component_name or component_uuid must be provided, along with device_uuid.
rpc DisableHWComponent(DisableHWComponentRequest) returns(DisableHWComponentResponse);
```
This RPC disables a hardware component on a managed device.  
You must provide the `device_uuid` and at least one of `component_name` or `component_uuid` in the request.  
If the operation is not supported or the parameters are invalid, an appropriate error will be returned in the response.

## ResetHWComponent
```protobuf
// Resets a hardware component on a device.
// At least one of component_name or component_uuid must be provided, along with device_uuid.
rpc ResetHWComponent(ResetHWComponentRequest) returns(ResetHWComponentResponse);
```
This RPC resets a hardware component on a managed device.  
You must provide the `device_uuid` and at least one of `component_name` or `component_uuid` in the request.  
If the operation is not supported or the parameters are invalid, an appropriate error will be returned in the response.

---

## Port Speed configuration
The Device Management Interface does not support runtime NNI (network to network interface) port speed configuration on the OLT device.
The speed of the NNI ports is configured, for each port, at startup time through the startup configuration file that can be provided via the
`UpdateStartupConfiguration` API. If a change to the NNI port speed is needed a new startup configuration will be sent
to the DM implementation for that OLT via the `UpdateStartupConfiguration` API.
The new configuration will then be applied by the DM to the OLT. This may include a reboot of the OLT.

Operators currently do not require runtime configuration of the NNI because it's not an element that is expected to change
at all once initial deployment is performed.

## Transceiver Technology Configuration
If the transceiver technology cannot be automatically detected on the OLT, the transceiver technology is set to `TYPE_NOT_DETECTED`
when the transceiver object is added to the model. In this case the `SetHWComponentInfo` API on the DMI can
be used to set the transceiver technology. Set `HWComponentInfoSetRequest.ModifiableComponent.TransceiverComponentChangeAttributes.TransceiverType`
to the relevant transceiver technology.

If the DM does not support setting transceiver technology, it should return the error code `SET_UNSUPPORTED` in `HWComponentInfoSetResponse`
if the user tries to change/set the technology.

The [Combo and Any PON support](https://docs.google.com/document/d/129YDzShMvYACsrM0dWV60tV79BRPI6SsBpf_nm0Byxc/edit?usp=sharing) has
more details about dynamic detection and configuration of PON technology. Although this document focuses on PON technology configuration aspects,
it still has some general concepts applicable for any other non-PON transceiver types.

