Subscriptions
Defining subscriptions with subscribe
command's CLI flags is a quick&easy way to work with gNMI subscriptions. A downside of that approach is that commands can get lengthy when defining multiple subscriptions.
With the multiple subscriptions defined in the configuration file we make a complex task of managing multiple subscriptions for multiple targets easy. The idea behind the multiple subscriptions is to define the subscriptions separately and then bind them to the targets.
Defining subscriptions#
To define a subscription a user needs to create the subscriptions
container in the configuration file:
subscriptions:
# a configurable subscription name
subscription-name:
# string, path to be set as the Subscribe Request Prefix
prefix:
# string, value to set as the SubscribeRequest Prefix Target
target:
# boolean, if true, the SubscribeRequest Prefix Target will be set to
# the configured target name under section `targets`.
# does not apply if the previous field `target` is set.
set-target: # true | false
# list of strings, list of subscription paths for the named subscription
paths: []
# list of strings, schema definition modules
models: []
# string, case insensitive, one of ONCE, STREAM, POLL
mode: STREAM
# string, case insensitive, if `mode` is set to STREAM, this defines the type
# of streamed subscription,
# one of SAMPLE, TARGET_DEFINED, ON_CHANGE
stream-mode: TARGET_DEFINED
# string, case insensitive, defines the gNMI encoding to be used for the subscription
encoding: JSON
# integer, specifies the packet marking that is to be used for the subscribe responses
qos:
# duration, Golang duration format, e.g: 1s, 1m30s, 1h.
# specifies the sample interval for a STREAM/SAMPLE subscription
sample-interval:
# duration, Golang duration format, e.g: 1s, 1m30s, 1h.
# The heartbeat interval value can be specified along with `ON_CHANGE` or `SAMPLE`
# stream subscriptions modes and has the following meanings in each case:
# - `ON_CHANGE`: The value of the data item(s) MUST be re-sent once per heartbeat
# interval regardless of whether the value has changed or not.
# - `SAMPLE`: The target MUST generate one telemetry update per heartbeat interval,
# regardless of whether the `--suppress-redundant` flag is set to true.
heartbeat-interval:
# boolean, if set to true, the target SHOULD NOT generate a telemetry update message unless
# the value of the path being reported on has changed since the last
suppress-redundant:
# boolean, if set to true, the target MUST not transmit the current state of the paths
# that the client has subscribed to, but rather should send only updates to them.
updates-only:
# historical subscription config: https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-history.md#1-purpose
history:
# string, nanoseconds since Unix epoch or RFC3339 format.
# if set, the history extension type will be a Snapshot request
snapshot:
# string, nanoseconds since Unix epoch or RFC3339 format.
# if set, the history extension type will be a Range request
start:
# string, nanoseconds since Unix epoch or RFC3339 format.
# if set, the history extension type will be a Range request
end:
Examples:
# part of ~/gnmic.yml config file
subscriptions: # container for subscriptions
port_stats: # a named subscription, a key is a name
paths: # list of subscription paths for that named subscription
- "/state/port[port-id=1/1/c1/1]/statistics/out-octets"
- "/state/port[port-id=1/1/c1/1]/statistics/in-octets"
stream-mode: sample # one of [on-change target-defined sample]
sample-interval: 5s
encoding: bytes
service_state:
paths:
- "/state/service/vpls[service-name=*]/oper-state"
- "/state/service/vprn[service-name=*]/oper-state"
stream-mode: on-change
system_facts:
paths:
- "/configure/system/name"
- "/state/system/version"
mode: once
Inside that subscriptions container a user defines individual named subscriptions; in the example above two named subscriptions port_stats
and service_state
were defined.
These subscriptions can be used on the cli via the [ --name ]
flag of subscribe command:
gnmic subscribe --name service_state --name port_stats
Or by binding them to different targets, (see next section)
Binding subscriptions#
Once the subscriptions are defined, they can be flexibly associated with the targets.
# part of ~/gnmic.yml config file
targets:
router1.lab.com:
username: admin
password: secret
subscriptions:
- port_stats
- service_state
router2.lab.com:
username: gnmi
password: telemetry
subscriptions:
- service_state
The named subscriptions are put under the subscriptions
section of a target container. As shown in the example above, it is allowed to add multiple named subscriptions under a single target; in that case each named subscription will result in a separate Subscription Request towards a target.
Note
If a target is not explicitly associated with any subscription, the client will subscribe to all defined subscriptions in the file.
The full configuration with the subscriptions defined and associated with targets will look like this:
username: admin
password: nokiasr0s
insecure: true
targets:
router1.lab.com:
subscriptions:
- port_stats
- service_state
- system_facts
router2.lab.com:
subscriptions:
- service_state
- system_facts
subscriptions:
port_stats:
paths:
- "/state/port[port-id=1/1/c1/1]/statistics/out-octets"
- "/state/port[port-id=1/1/c1/1]/statistics/in-octets"
stream-mode: sample
sample-interval: 5s
encoding: bytes
service_state:
paths:
- "/state/service/vpls[service-name=*]/oper-state"
- "/state/service/vprn[service-name=*]/oper-state"
stream-mode: on-change
system_facts:
paths:
- "/configure/system/name"
- "/state/system/version"
mode: once
As a result of such configuration the gnmic
will set up three gNMI subscriptions to router1 and two other gNMI subscriptions to router2:
$ gnmic subscribe
gnmic 2020/07/06 22:03:35.579942 target 'router2.lab.com' initialized
gnmic 2020/07/06 22:03:35.593082 target 'router1.lab.com' initialized
{
"source": "router2.lab.com",
"subscription-name": "service_state",
"timestamp": 1594065869313065895,
"time": "2020-07-06T22:04:29.313065895+02:00",
"prefix": "state/service/vpls[service-name=testvpls]",
"updates": [
{
"Path": "oper-state",
"values": {
"oper-state": "down"
}
}
]
}
{
"source": "router1.lab.com",
"subscription-name": "service_state",
"timestamp": 1594065868850351364,
"time": "2020-07-06T22:04:28.850351364+02:00",
"prefix": "state/service/vpls[service-name=test]",
"updates": [
{
"Path": "oper-state",
"values": {
"oper-state": "down"
}
}
]
}
{
"source": "router1.lab.com",
"subscription-name": "port_stats",
"timestamp": 1594065873938155916,
"time": "2020-07-06T22:04:33.938155916+02:00",
"prefix": "state/port[port-id=1/1/c1/1]/statistics",
"updates": [
{
"Path": "in-octets",
"values": {
"in-octets": "671552"
}
}
]
}
{
"source": "router1.lab.com",
"subscription-name": "port_stats",
"timestamp": 1594065873938043848,
"time": "2020-07-06T22:04:33.938043848+02:00",
"prefix": "state/port[port-id=1/1/c1/1]/statistics",
"updates": [
{
"Path": "out-octets",
"values": {
"out-octets": "370930"
}
}
]
}
^C
received signal 'interrupt'. terminating...