
= OpenConfig Telemetry
:description: Learn how to stream OpenConfig telemetry data over gRPC to OpenNMS {page-component-title}.

https://www.openconfig.net/[OpenConfig] is an open-source initiative by network operators to develop vendor-neutral data models, programmatic interfaces, and tools for managing networks.

The OpenConfig client lets you stream OpenConfig telemetry data over gRPC to {page-component-title}.
Some vendors currently using OpenConfig telemetry include Juniper, Arista, and Cisco.

To enable support for OpenConfig, edit `$OPENNMS_HOME/etc/telemetryd-configuration.xml` to set `enabled=true` for the OpenConfig protocol.

OpenConfig can be enabled on both {page-component-title} Core and Minion deployments.
For Minion setup instructions, see <<minion-setup, Set up OpenConfig on Minion>>.

.Enable OpenConfig protocol in telemetryd-configuration.xml
[source, xml]
----
<!-- OpenConfig -->
<connector name="OpenConfig-Connector"
            class-name="org.opennms.netmgt.telemetry.protocols.openconfig.connector.OpenConfigConnector"
            service-name="OpenConfig"
            queue="OpenConfig"
            enabled="true">
    <package name="OpenConfig-Default">
        <filter>IPADDR != '0.0.0.0'</filter>
        <parameter key="port" value="${requisition:oc.port|9000}"/>
        <parameter key="paths" value="${requisition:oc.paths|/network-instances/network-instance[instance-name=master],/protocols/protocol/bgp}"/>
        <parameter key="mode" value="${requisition:oc.mode|gnmi}"/>
    </package>
</connector>

<queue name="OpenConfig">
    <adapter name="OpenConfig-Adapter" class-name="org.opennms.netmgt.telemetry.protocols.openconfig.adapter.OpenConfigAdapter" enabled="true">
        <parameter key="script" value="$OPENNMS_HOME/etc/telemetryd-adapters/openconfig-telemetry-resources.groovy"/>
        <package name="OpenConfig-Default">
            <rrd step="300">
                <rra>RRA:AVERAGE:0.5:1:2016</rra>
                <rra>RRA:AVERAGE:0.5:12:1488</rra>
                <rra>RRA:AVERAGE:0.5:288:366</rra>
                <rra>RRA:MAX:0.5:288:366</rra>
                <rra>RRA:MIN:0.5:288:366</rra>
            </rrd>
        </package>
    </adapter>
</queue>
----

Apply the changes without restarting by sending a `reloadDaemonConfig` event in the CLI or the Web UI:

.Send a reloadDaemonConfig event through CLI
[source, console]
----
$OPENNMS_HOME/bin/send-event.pl -p 'daemonName Telemetryd' uei.opennms.org/internal/reloadDaemonConfig
----

== OpenConfig connector

OpenConfig Connector initiates a connection with an agent via gRPC and subscribes to one or more OpenConfig data paths (strings), then collects and forwards the data to a queue.
The data contains metadata and is structured as a list of `key:value` pairs.

{page-component-title} creates a new connector for each agent it is responsible for connecting to.

=== Connector configuration

[source, xml]
----
<connector name="OpenConfig-Connector"
            class-name="org.opennms.netmgt.telemetry.protocols.openconfig.connector.OpenConfigConnector"
            service-name="OpenConfig"
            queue="OpenConfig"
            enabled="true">
    <package name="OpenConfig-Default">
        <filter>IPADDR != '0.0.0.0'</filter>
        <parameter key="port" value="${requisition:oc.port|9000}"/>
        <parameter key="paths" value="${requisition:oc.paths|/network-instances/network-instance[instance-name=master],/protocols/protocol/bgp}"/>
        <parameter key="mode" value="${requisition:oc.mode|gnmi}"/>
        <parameter key="retries" value="12"/>
        <parameter key="interval" value="300"/>
        <parameter key="username" value="admin"/>
        <parameter key="password" value="admin"/>
        <parameter key="tls.enabled" value="${requisition:oc.tls.enabled}"/>
        <parameter key="tls.trust.cert.path" value="${requisition:trust.cert.path}"/>
        <!-- Use groups to separate paths that need to be streamed at different frequencies -->
        <parameter group="group1" key="paths" value="${requisition:oc.paths|/network-instances/network-instance[instance-name=master]}"/>
        <parameter group="group1" key="frequency" value="5000"/>
        <parameter group="group2" key="paths" value="${requisition:oc.paths|/protocols/protocol/bgp}"/>
        <parameter group="group2" key="frequency" value="30000"/>
        <parameter group="group3" key="paths" value="${requisition:oc.paths|/interfaces/interface[name=Ethernet1][ifIndex=25]/state/counters}"/>
        <parameter group="group3" key="frequency" value="60000"/>
    </package>
</connector>
----


=== Service
For any interface that needs to enable OpenConfig streaming, we need to add a service on a given interface.
This denotes `service-name` in above configuration which is defined as `OpenConfig`.

=== Packages
At least one package must be present for the connector to function.
Use multiple packages to customize the parameter's subsets of nodes.

The `filter` element is optional.
If missing, all services with the given name will be considered.

Use the `group` element to group parameters into multiple groups when you need to stream different paths at different frequencies.
Global parameters like port, and connection-specific parameters, do not need any group.

Parameters are passed to the connector and are interpolated for node/interface and service-level metadata.

.Connector-specific parameters for the OpenConfigConnector
[options="header" cols="1,3,3"]
|===
| Parameter
| Description
| Default

3+| *Required*

| port
| Port that OpenConfig client can connect to.
| 9000

| paths
| One or more OpenConfig paths to subscribe to. Multiple paths can be comma-separated.
| /network-instances/network-instance[instance-name=master],/protocols/protocol/bgp

| frequency
| Frequency at which OpenConfig data can be streamed. This is parsed as milliseconds (ms) for jti and nanoseconds (ns) for gnmi.
| 300000

3+| *Optional*

| retries
| Number of retries to attempt to make a connection when failed.
| 0

| interval
| Interval at which client tries to make a connection when failed in seconds.
| 300

| hostname
| The HostName OpenNMS needs to make a gRPC connection instead of using Node primary IpAddress.
| none

| tls.enabled
| Enable TLS authentication.
| false

| tls.trust.cert.path
| Root CA certificate for verifying server certs
| none

| tls.client.key.path
| Client private key path
| none

| tls.client.cert.path
| Client public certificate path
| none

| tls.skip.verify
| Skip TLS signature verification (TLS certs are still used, test purposes only)
| false

| origin
| Origin that need to be subscribed to, only relevant for gnmi.
| openconfig

| username
| Username that can be used to authenticate, sent as metadata to the server.
| none

| password
| Password that can be used to authenticate, sent as metadata to the server.
| none


| mode
| Specify mode for stream format. Options include gnmi or jti.
| gnmi
|===

=== Configure requisitions for OpenConfig

To enable OpenConfig on a device, you must add metadata that defines the OpenConfig configuration.

. In the web UI, click menu:Manage Inventory[Provisioning Requisitions].
. Select an existing requisition or create a new one by clicking *Add Requisition*.
. Edit a node or add a new node by clicking *Add Node*.
. On the interface where you want to enable OpenConfig streaming, add the *OpenConfig* service (or the `service-name` specified in your connector configuration).
. Click *Add Meta-Data* and define the following key-value pairs:
.. `oc.port`: Port of the OpenConfig gRPC server (default: 9000).
.. `oc.paths`: One or more OpenConfig paths to subscribe to; multiple paths should be comma-separated.
.. `oc.mode`: Stream format (gnmi or jti; default: gnmi).
.. (Optional) `oc.tls.enabled`: Set to `true` to enable TLS.
.. (Optional) `trust.cert.path`: Path to root CA certificate for TLS verification.
. Click *Save* to save the metadata, then *Save* again to save the requisition.
. Click *Return*, then click *Synchronize*.
. Choose a scan option and click *Synchronize*.

The OpenConfig connector will now establish a connection to the device and begin streaming telemetry data.

[[minion-setup]]
=== Set up OpenConfig on Minion

Before setting up OpenConfig on Minion, ensure that a message broker is configured.
See xref:deployment:core/setup-message-broker.adoc[Set up message broker] for details.

IMPORTANT: Currently, the Twin API distributes OpenConfig configuration to all Minions at a given location. To avoid duplicate data collection, install the `minion-telemetry-openconfig-client` feature on only one Minion per location.

. On the Minion, install the OpenConfig feature:
+
[source, console]
----
feature:install minion-telemetry-openconfig-client
----

. Verify that the feature is installed and started:
+
[source, console]
----
admin@minion()> feature:status minion-telemetry-openconfig-client
Started
----

. Configure the OpenConfig connector and adapter on {page-component-title} Core as described in the sections above.
The Minion will automatically receive the configuration through the Twin API and begin streaming telemetry data from configured devices.

=== Stop or disable OpenConfig on a node

To stop OpenConfig on a node, you must remove the service from both the node and the requisition:

. Delete the service from the node:
.. In the side menu, click menu:Nodes[] to open the Nodes List page.
.. Select the node where you want to stop OpenConfig.
.. In the *Availability* section, locate the OpenConfig service (or the service name specified in the `connector` within `telemetryd-configuration.xml`).
.. Click *Delete* to remove the service.
This immediately stops the OpenConfig connector for this node.

. Remove the service from the requisition to prevent it from being re-added:
.. Click menu:Manage Inventory[Provisioning Requisitions].
.. Select the requisition containing the node.
.. Edit the node and locate the interface with the OpenConfig service.
.. Remove the OpenConfig service from the interface.
.. Remove any OpenConfig-related metadata (oc.port, oc.paths, oc.mode, etc.).
.. Click *Save* to save the changes to the node, then *Save* again to save the requisition.
.. Click *Return*, then click *Synchronize* to apply the changes.

The OpenConfig service will remain stopped and will not be re-added during future synchronizations.

== OpenConfig adapter

The OpenConfig adapter handles OpenConfig payloads.
Messages are decoded and forwarded to a JSR-223-compatible script (for example, BeanShell or Groovy) for further processing.
Use the script extension to extract the desired metrics from the OpenConfig stream data and persist the results as time series data.

=== Facts

[options="autowidth"]
|===
| Class Name          | `org.opennms.netmgt.telemetry.protocols.openconfig.adapter.OpenConfigAdapter`
|===

=== Configuration and use

.Adapter-specific parameters for the OpenConfigAdapter
[options="header", cols="1,3,1"]
|===
| Parameter
| Description
| Default

3+| *Required*

| script
| Full path to the script that handles the OpenConfig data.
| none

3+| *Optional*

| mode
| Specify mode for stream format. Options include gnmi or jti.
Options are `gnmi` or `jti`.
| gnmi
|===

=== Scripting

The script will be invoked for every OpenConfig stream data that is received and successfully decoded.

The following globals will be passed to the script:

.Globals passed to the script for gNMI (default) mode.
[options="header", cols="1,3,3"]
|===
| Parameter
| Description
| Type

| agent
| The agent (node) against which the metrics will be associated.
| org.opennms.netmgt.collection.api.CollectionAgent

| builder
| Builder in which the resources and metrics should be added.
| org.opennms.netmgt.collection.support.builder.CollectionSetBuilder

| msg
| Decoded message from which the metrics should be extracted.
| org.opennms.features.openconfig.proto.gnmi.Gnmi.SubscribeResponse
|===

.Globals passed to the script for JTI mode.
[options="header", cols="1,3,3"]
|===
| Parameter
| Description
| Type

| agent
| The agent (node) against which the metrics will be associated.
| org.opennms.netmgt.collection.api.CollectionAgent

| builder
| Builder in which the resources and metrics should be added.
| org.opennms.netmgt.collection.support.builder.CollectionSetBuilder

| msg
| Decoded message from which the metrics should be extracted.
| org.opennms.features.openconfig.proto.jti.Telemetry.OpenConfigData
|===
