From e0ed9c13829b46772485b9e819fca70e465470ea Mon Sep 17 00:00:00 2001 From: <> Date: Fri, 9 Aug 2024 12:45:23 +0000 Subject: [PATCH] Deployed 4d2938a with MkDocs version: 1.6.0 --- .nojekyll | 0 404.html | 992 + _media/favicon.ico | Bin 0 -> 4286 bytes assets/images/favicon.png | Bin 0 -> 1870 bytes assets/javascripts/bundle.a00a7c5e.min.js | 29 + assets/javascripts/bundle.a00a7c5e.min.js.map | 8 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 + .../workers/search.db81ec45.min.js | 42 + .../workers/search.db81ec45.min.js.map | 8 + assets/stylesheets/main.0d440cfe.min.css | 1 + assets/stylesheets/main.0d440cfe.min.css.map | 1 + assets/stylesheets/palette.2505c338.min.css | 1 + .../stylesheets/palette.2505c338.min.css.map | 1 + configuration/mtls/index.html | 1517 + configuration/netconf/index.html | 1124 + configuration/openconfig/index.html | 1658 + configuration/restconf/index.html | 1213 + configuration/security/index.html | 1196 + examples/WiFi/index.html | 1492 + examples/ansible/index.html | 1187 + examples/gnmi-clients/arista-gnmi/index.html | 2778 + examples/gnmi-clients/gnmic/index.html | 3360 + examples/gnmi-clients/gnmic/outputs/bgp.json | 145 + .../gnmic/outputs/capabilities.json | 130 + examples/gnmi-clients/gnmic/outputs/doms.json | 102508 +++++++++++++++ .../gnmi-clients/gnmic/outputs/eos_image.json | 63 + .../gnmic/outputs/interface_state.json | 13639 ++ .../gnmic/outputs/network-instances.json | 1112 + examples/gnmi-gateway/index.html | 1277 + examples/gnoi/gnoic/index.html | 1463 + examples/gnoi/gnoicode/index.html | 1389 + examples/gnoi/grpcurl/index.html | 1568 + examples/gnoi/index.html | 1129 + examples/golang/index.html | 1161 + examples/index.html | 1058 + examples/netconf/index.html | 1081 + examples/netconf/ncclient/index.html | 1388 + examples/netconf/netconf_over_ssh/index.html | 1749 + examples/pyang/index.html | 1627 + examples/pyang/requirements.txt | 1 + examples/pyangbind/demo.json | 36 + examples/pyangbind/index.html | 1408 + examples/pygnmi/index.html | 1936 + examples/pygnmi/requirements.txt | 1 + examples/restconf/curl/index.html | 1554 + examples/restconf/index.html | 1124 + examples/restconf/python/index.html | 1256 + examples/ygot/images/ygot.png | Bin 0 -> 131037 bytes examples/ygot/index.html | 1298 + index.html | 1105 + models/index.html | 1172 + protocols/index.html | 1108 + search/search_index.json | 1 + sitemap.xml | 168 + sitemap.xml.gz | Bin 0 -> 439 bytes stylesheets/extra.material.css | 76 + telemetry/adapters/gnmireverse/index.html | 1474 + telemetry/adapters/kafka/index.html | 1418 + telemetry/index.html | 1127 + videos/index.html | 1216 + 87 files changed, 173769 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 _media/favicon.ico create mode 100644 assets/images/favicon.png create mode 100644 assets/javascripts/bundle.a00a7c5e.min.js create mode 100644 assets/javascripts/bundle.a00a7c5e.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.db81ec45.min.js create mode 100644 assets/javascripts/workers/search.db81ec45.min.js.map create mode 100644 assets/stylesheets/main.0d440cfe.min.css create mode 100644 assets/stylesheets/main.0d440cfe.min.css.map create mode 100644 assets/stylesheets/palette.2505c338.min.css create mode 100644 assets/stylesheets/palette.2505c338.min.css.map create mode 100644 configuration/mtls/index.html create mode 100644 configuration/netconf/index.html create mode 100644 configuration/openconfig/index.html create mode 100644 configuration/restconf/index.html create mode 100644 configuration/security/index.html create mode 100644 examples/WiFi/index.html create mode 100644 examples/ansible/index.html create mode 100644 examples/gnmi-clients/arista-gnmi/index.html create mode 100644 examples/gnmi-clients/gnmic/index.html create mode 100644 examples/gnmi-clients/gnmic/outputs/bgp.json create mode 100644 examples/gnmi-clients/gnmic/outputs/capabilities.json create mode 100644 examples/gnmi-clients/gnmic/outputs/doms.json create mode 100644 examples/gnmi-clients/gnmic/outputs/eos_image.json create mode 100644 examples/gnmi-clients/gnmic/outputs/interface_state.json create mode 100644 examples/gnmi-clients/gnmic/outputs/network-instances.json create mode 100644 examples/gnmi-gateway/index.html create mode 100644 examples/gnoi/gnoic/index.html create mode 100644 examples/gnoi/gnoicode/index.html create mode 100644 examples/gnoi/grpcurl/index.html create mode 100644 examples/gnoi/index.html create mode 100644 examples/golang/index.html create mode 100644 examples/index.html create mode 100644 examples/netconf/index.html create mode 100644 examples/netconf/ncclient/index.html create mode 100644 examples/netconf/netconf_over_ssh/index.html create mode 100644 examples/pyang/index.html create mode 100644 examples/pyang/requirements.txt create mode 100644 examples/pyangbind/demo.json create mode 100644 examples/pyangbind/index.html create mode 100644 examples/pygnmi/index.html create mode 100644 examples/pygnmi/requirements.txt create mode 100644 examples/restconf/curl/index.html create mode 100644 examples/restconf/index.html create mode 100644 examples/restconf/python/index.html create mode 100644 examples/ygot/images/ygot.png create mode 100644 examples/ygot/index.html create mode 100644 index.html create mode 100644 models/index.html create mode 100644 protocols/index.html create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz create mode 100644 stylesheets/extra.material.css create mode 100644 telemetry/adapters/gnmireverse/index.html create mode 100644 telemetry/adapters/kafka/index.html create mode 100644 telemetry/index.html create mode 100644 videos/index.html diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..f89a30ba --- /dev/null +++ b/404.html @@ -0,0 +1,992 @@ + + + +
+ + + + + + + + + + + + + + + + + +EOS supports the use of mutual TLS (mTLS) for gRPC, RESTCONF and eAPI services. This allows the use of certificates, +signed by a recognized and trusted CA, for authentication to gNMI and other gRPC based services.
+By default only certificates signed with Arista's CA are trusted. In order to generate and sign certificates for mTLS +authentication, an operator will need to install and configure a certifying authority (CA) that is used for signing +certificates that are generated on network elements as well as the servers that will be interacting with the gRPC +services. The necessary certificates for establishing the chain of trust will need to be imported into the switches and +tools interacting with the switches.
+This document outlines the necessary steps to generate certificate signing requests (CSR) on arista devices, sign the +certificates and import these into the switches.
+The simple installation of Easy-RSA is well documented in the Easy RSA quick start +guide. For a more durable installation you're +encouraged to review the Easy-RSA documentation and customize the settings to your environment.
+easy RSA version: 3.0.8
+As of this writing EOS only supports RSA certificates, this differs from the default configuration of Easy-RSA. The
+following variable in the vars
file will need to be set in order to generate the appropriate certificate type.
Use the easyrsa build-ca
command to create the necessary certificate signing infrastructure within easyrsa. This will
+generate a ca.crt
certificate which can be imported into the PKI validation chain of the switches and other hosts in
+your PKI domain. This can also be used in a standalone manner with most gnmi clients.
In our case, this CA certificate resides in: ${HOME}/easy-rsa/pki/ca.crt
This will need to be imported into the network elements where you're using mTLS for authentication.
+This will be used by local clients (gnmi, gnoi, gribi, etc.) connecting to the switches in order to authenticate.
+Note the gnmi-client.cnf
configuration file provided in the following openssl
command is used to create the Subject
+Alternate Name IP address entry associated with the client certificate. This is optional and is not required for
+certificates.
mkdir ~/gnmi-client-cert
+cd ~/gnmi-client-cert
+openssl req -out gnmi-client.csr -newkey rsa:2048 -nodes -keyout gnmi-client.key -config gnmi-client.cnf
+
The above commands will generate a private key as well as the Certificate Signing Request (CSR)
+Note, that this is going to be a client certificate. As our gnmi client will be talking to the gnmi server on the +switch.
+cd ~/easy-rsa
+./easyrsa import-req ../gnmi-client-cert gnmi-client.csr gnmi-client
+./easyrsa sign-req client gnmi-client
+
The sign-req
command generates the following output.
Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020
+
+... snipped ...
+
+subject=
+ countryName = us
+ stateOrProvinceName = mn
+ localityName = minneapolis
+ organizationName = arista-lab
+ commonName = sulrich@arista.com
+
+X509v3 Subject Alternative Name:
+ IP:192.168.1.11
+
+
+Type the word 'yes' to continue, or any other input to abort.
+ Confirm request details: yes
+Using configuration from /home/sulrich/easy-rsa/pki/easy-rsa-3625384.5yQThV/tmp.kaJhk0
+Check that the request matches the signature
+Signature ok
+The Subject's Distinguished Name is as follows
+countryName :PRINTABLE:'us'
+stateOrProvinceName :ASN.1 12:'mn'
+localityName :ASN.1 12:'minneapolis'
+organizationName :ASN.1 12:'arista-lab'
+commonName :ASN.1 12:'sulrich@arista.com'
+Certificate is to be certified until Oct 10 19:45:42 2023 GMT (825 days)
+
+Write out database with 1 new entries
+Data Base Updated
+
+Certificate created at: /home/sulrich/easy-rsa/pki/issued/gnmi-client.crt
+
v1.key
Note that in this case we're generating a server certificate.
+ +This will generate the signed certificate and place it into the easy-rsa local store.
+${HOME}/easy-rsa/pki/issued/v1.crt
copy file:/mnt/flash/v1.crt certificate:v1.crt
You will need to copy the CA.crt
(commonly in <easyrsa_root>/pki/ca.crt
) to the switch and add it to the list of
+certificates. In the following example the file has been copied to the switch as demo-ca.crt
.
Configure the necessary ssl profile
and include the demo-ca.crt
in the list of trusted CAs.
management security
+ ssl profile test-arista
+ certificate v1.crt key v1.key
+ trust certificate demo-ca.crt
+!
+
The following configuration associates the gnmi service with the associated ssl profile and enables it for use with mTLS +for authentication.
+ +At this point the switch is configured to accept connections from clients with valid, signed certificates.
+show management api gnmi
This command enables you to determine the operational state of the gnmi process as well as whether or not the ssl profile +is considered valid.
+show management security ssl profile
This command enables you to see the state of the ssl profiles and whether there are issues with the validation chain.
+Certificates should be created with a finite lifetime and rotated within that lifetime. However, if the clocks on the +switch are grossly off this may impact certificate operation. Make sure that the clock on the switch is set correctly +and synchronized to a reliable time source.
+gnmi -addr 192.168.1.21:6030 \
+ -username admin -password arista \
+ -cafile easy-rsa/pki/ca.crt \
+ -certfile easy-rsa/pki/issued/gnmi-client.crt \
+ -keyfile gnmi-client/gnmi-client.key capabilities
+
gnmic -a 192.168.1.21:6030 -u admin -p arista \
+ --tls-ca easy-rsa/pki/ca.crt \
+ --tls-cert easy-rsa/pki/issued/gnmi-client.crt \
+ --tls-key gnmi-client/gnmi-client.key capabilities
+
EOS provides support for managing the switch via NETCONF.
+Currently supported NETCONF operations: get, get-config, get-schema, +edit-config, lock, unlock, close-session, kill-session.
+To configure NETCONF in default VRF we can enable the ssh transport under
+management api netconf
:
Default VRF
+ +Non-default VRF
+ +Changing the port:
+ +Apply ACL
+ +Note The ACL should be a standard ACL allowing hosts or subnets.
+Status check:
+ + + + + + + + + +EOS supports the OpenConfig gNMI interface for device management.
+All EOS flavors support OpenConfig (physical, virtual, containerized, cloud).
+To start the gNMI server, which listens by default on TCP/6030 configure the gRPC transport under management api gnmi
+in the global config mode:
Default VRF
+ +Non-default VRF
+ +Changing the port:
+ +Apply ACL
+ +Note, the ACL should be a standard ACL allowing hosts or subnets.
+Authenticate the connection with TLS
+ +Enable authorization of incoming requests
+ +Status check
+#show management api gnmi
+Octa: No
+Enabled: Yes
+Server: running on port 6030, in default VRF
+SSL Profile: none
+QoS DSCP: none
+
The OpenConfig agent (gNMI API) can leverage the EOS state streaming agent's (TerminAttr) libraries, thus exposing EOS
+native paths. If Octa (OpenConfig + TerminAttr) is enabled then OpenConfig, in addition to accepting OpenConfig paths in
+gNMI get/subscribe requests, will also support EOS native paths (for example, Sysdb/Smash paths). This feature was
+introduced in 4.22.1F
.
gNMI requests received by Octa are interpreted as either OpenConfig or TerminAttr requests, as follows.
+eos_native
are processed as as native path requests.eos_native
are treated as OpenConfig requests.A gNMI client that supports specification of an origin as part of the associated RPC is a requirement.
+Note support for sending GET/SUBSCRIBE requests to both an openconfig and an eos-native path in the same call is not yet +supported.
+Octa can be enable by adding provider eos-native
under management api gnmi
SW(config-mgmt-api-gnmi)#provider eos-native
Status check
+#show management api gnmi
+Octa: enabled
+Enabled: Yes
+Server: running on port 6030, in default VRF
+SSL Profile: none
+QoS DSCP: none
+
Starting in EOS 4.24.0F
it is possible to configure the Smash paths that Octa has access to. Under the management api
+models
mode, the provider smash sub-mode allows for enabling or disabling a Smash path with the [no] path
+smash_path_here [disabled]
command.
management api models
+ provider smash
+ path forwarding/status
+ path routing/status disabled
+ path routing/isis/lsdb
+
Note that every time a new path is added the Octa agent has to be restarted. +EOS CLI:
+ +Bash:
+$ sudo killall Octa
Alternatively agent Octa terminate
can be used from EOS CLI as well.
show management api models
will list the Smash paths enabled/disabled
e.g.:
+#show management api models
+provider smash
+ path /Smash/bridging
+ path /Smash/forwarding/status
+ path /Smash/routing/isis/lsdb
+ path /Smash/routing
+ path /Smash/routing/status disabled
+provider sysdb
+
Starting with EOS 4.27.2F accounting requests
can be enabled to account records for gNMI/gNOI RPCs:
management api gnmi
+ transport grpc default
+ authorization requests
+ accounting requests
+ provider eos-native
+!
+aaa accounting commands all default start-stop logging
+
we can also use these commands to log to tacacs+ or radius and syslog too
+aaa accounting commands all default start-stop group tacacs+
+aaa accounting commands all default start-stop group radius
+
spine1# sh management api gnmi
+Octa: enabled
+
+Transport: default
+Enabled: yes
+Server: running on port 6030, in default VRF
+SSL profile: none
+QoS DSCP: none
+Authorization required: yes
+Accounting requests: yes
+Certificate username authentication: no
+Notification timestamp: last change time
+Listen addresses: ::
+spine1#
+
Configuration change using OpenConfig and gNMI:
+$ gnmic -a 192.168.0.10:6030 -u arista -p arista77rx --insecure set --update-path "/interfaces/interface[name=Ethernet1]/config/description" --update-value "test"
+{
+ "source": "192.168.0.10:6030",
+ "timestamp": 1663615213475353999,
+ "time": "2022-09-19T19:20:13.475353999Z",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "interfaces/interface[name=Ethernet1]/config/description"
+ }
+ ]
+}
+
$ gnmic -a 192.168.0.10:6030 -u arista -p arista77rx --insecure get --path "/interfaces/interface[name=Ethernet1]/config/description"
+[
+ {
+ "source": "192.168.0.10:6030",
+ "timestamp": 1663615224964145128,
+ "time": "2022-09-19T19:20:24.964145128Z",
+ "updates": [
+ {
+ "Path": "interfaces/interface[name=Ethernet1]/config/description",
+ "values": {
+ "interfaces/interface/config/description": "test"
+ }
+ }
+ ]
+ }
+]
+
Syslog messages on the device:
+spine1#sh logging last 5 minutes
+Sep 19 19:20:13 spine1 Aaa: %ACCOUNTING-6-CMD: arista unknown unknown stop task_id=34 start_time=1663615213.48 timezone=UTC service=shell priv-lvl=15 cmd=OpenConfig.Set addr=192.168.0.1:57388 rpc=/gnmi.gNMI/Set request={"update":[{"path":"/interfaces/interface[name=Ethernet1]/config/description","val":"\\"test\\""}]} <cr>
+Sep 19 19:20:13 spine1 ConfigAgent: %SYS-5-CONFIG_SESSION_ENTERED: User arista entered configuration session session11521733719371 on GNMI (192.168.0.1:57388)
+Sep 19 19:20:13 spine1 ConfigAgent: %SYS-5-CONFIG_SESSION_COMMIT_SUCCESS: User arista committed configuration session session11521733719371 successfully on GNMI (192.168.0.1:57388)
+Sep 19 19:20:13 spine1 ConfigAgent: %SYS-5-CONFIG_SESSION_EXITED: User arista exited configuration session session11521733719371 on GNMI (192.168.0.1:57388)
+Sep 19 19:20:24 spine1 Aaa: %ACCOUNTING-6-CMD: arista unknown unknown stop task_id=35 start_time=1663615224.96 timezone=UTC service=shell priv-lvl=15 cmd=OpenConfig.Get addr=192.168.0.1:57428 rpc=/gnmi.gNMI/Get request={"path":[{"path":"/interfaces/interface[name=Ethernet1]/config/description"}]} <cr>
+
spine1#trace monitor octa
+--- Monitoring /var/log/agents/Octa-3748 ---
+I0919 19:20:13.715618 3748 router.go:234] Cli commands:
+configure session session11521733719371
+interface Ethernet1
+description test
+exit
+configure session session11521733719371 commit
+^Cspine1#
+
spine1#bash more /var/log/agents/Octa-3748 | tail -4
+interface Ethernet1
+description test
+exit
+configure session session11521733719371 commit
+spine1#
+
An accounting record is limited to a maximum of 8098 characters. +The record will be truncated if it exceeds the maximum character length.
+Starting in EOS 4.24.1F
it is possible to perform authorization of each RPC (that is, GET, SET, SUBSCRIBE), if
+authorization requests is supplied as described above.
During authorization, the OpenConfig agent will communicate with the AAA agent, allowing authorization policies or roles
+to permit or deny the new tokens OpenConfig.Get
and OpenConfig.Set
.
For example, a role may be defined such as:
+ +A user which is assigned to this role would be allowed to issue a gNMI GET or SUBSCRIBE request, but not a SET request.
+++Note that this is only available for gNMI.
+
By default, mapping of the FIB (forwarding information base) to the OpenConfig AFT (abstract forwarding table) model is +disabled, as the volume of data can be large.
+Starting in EOS 4.25.1F
it is possible to enable these mappings, for IPV4, IPV6, or both, as described below:
++Note that prior to EOS 4.27 a restart of the gNMI agent is required, e.g.:
+agent Octa terminate
or +agent OpenConfig terminate
(in case the eos-native provider is not enabled).
Per the GNMI specification, the default timestamp field of a notification message is set to be the time at which the +value of the underlying data source changes or when the reported event takes place. In order to facilitate integration +in legacy environments oriented around polling style operations, an option to support overriding the timestamp field to +the send-time is available. (as of 4.27.0F)
+Overriding the timestamp to send-time
is applicable to all STREAM and POLL subscriptions.
Configuration is outlined below.
+ +If there's a need to return to the standards-oriented operation, the following mechanisms can be used to reset the +behavior.
+no notification timestamp send-time
+default notification timestamp
+notification timestamp last-change-time
+
+ +
#show management api gnmi
+Octa: enabled
+Set persistence: enabled
+
+Transport: default
+Enabled: yes
+Server: running on port 6030, in default VRF
+SSL profile: none
+QoS DSCP: none
+Authorization required: no
+Accounting requests: no
+Certificate username authentication: no
+Notification timestamp: send time !! note: timestamp mode
+Listen addresses: ::
+
By default, within EOS, the application of gNMI Set
RPCs are not persisted to the startup-config
. A copy
+running-config startup-config
is required in order to save configuration updates imposed via gNMI.
As of EOS 4.28.0F, if the operator desires to be able to save gNMI-driven configuration automatically, persistence can be
+enabled by adding the following configuration. With this option, all gnmi Set
operations will be saved to the
+startup-config
. Note, the configuration is saved using Arista's EOS configuration syntax and there is no corresponding
+presentation of the OpenConfig syntax.
If there is a need to return to the default mode of gNMI configuration non-persistence, this can be disabled using the +following commands.
+ ++ +
#show management api gnmi
+Octa: enabled
+Set persistence: enabled !! note: persistence state
+
+Transport: default
+Enabled: yes
+Server: running on port 6030, in default VRF
+SSL profile: none
+QoS DSCP: none
+Authorization required: no
+Accounting requests: no
+Certificate username authentication: no
+Notification timestamp: last change time
+Listen addresses: ::
+
The OpenConfig agent handles all transports described above: gNMI, RESTCONF, and
+NETCONF. The agent log file is present at /var/log/agents/OpenConfig-{PID}
.
+Lines that begin with E
are errors. Debug logging can be enabled with a
+regular trace command. Here are a couple of examples:
(config)#trace OpenConfig setting server/9
- For server (gNMI) traces
(config)#trace OpenConfig setting */9
- For all traces with verbose setting
similarly if Octa is enabled:
+(config)#trace Octa setting server/9
- For server (gNMI) traces
(config)#trace Octa setting */9
- For all traces with verbose setting
4.24.0F
, not all Smash paths were accessible via Octa.4.24.0F
configuring the Smash paths that Octa has access to will also affect OpenConfig. Enabling a
+ Smash path for Octa can result in extra YANG paths being populated in OpenConfig. Disabling a Smash path can result in
+ having some YANG paths missing in OpenConfig.%<zone-id>
optional suffix in YANG ietf:ipv4-address
, and ietf:ipv6-address
types are not supported.Please refer to the EOS Central TOIs to see the new list of paths supported per release.
+For convenience, supported paths may be found at: https://eos.arista.com/path-report.
+EOS provides support for RESTCONF and the necessary transport services to support it.
+The RESTCONF server is in the EOS device.
+Certificate-based authentication is required for RESTCONF to operate. You should follow the instructions in the +Certificate Authentication section in order to generate and install a certificate to support +RESTCONF in your environment. Alternately, a self-signed certificate may be generated on the switch and certificate +validation can be handled appropriately by remote RESTCONF clients.
+The following Cli command generates a self-signed cert:
+security pki certificate generate self-signed restconf.crt key restconf.key generate rsa 2048 parameters common-name restconf
+
Create ssl profile:
+ +Configure RESTCONF:
+Default VRF:
+ +Non-default VRF
+ +Changing the port:
+ +Apply ACL
+ +++Note The ACL should be a standard ACL allowing hosts or subnets.
+
The default RESTCONF port on Arista devices is TCP 6020.
+We need to change the default control-plane ACL on EOS in order to allow TCP 6020 (or to allow the configured RESTCONF port).
+Please refer to this link
+When changing the default ports one has to make sure they are also allowed in the control-plane ACL. The default
+control-plane ACL cannot be modified, so a new one has to be created and applied under system control-plane
(EOS
+4.23+
) or control-plane
(pre-EOS 4.23
). The fastest way to do this is to clone the existing control-plane and add
+new permit rules.
1. Reading the default CP ACL can be done with show ip access-lists default-control-plane-acl
#show ip access-lists default-control-plane-acl
+IP Access List default-control-plane-acl [readonly]
+ counters per-entry
+ 10 permit icmp any any [match 7172 packets, 1 day, 20:46:09 ago]
+ 20 permit ip any any tracked [match 98544013 packets, 0:00:36 ago]
+ 30 permit udp any any eq bfd ttl eq 255
+ 40 permit udp any any eq bfd-echo ttl eq 254
+ 50 permit udp any any eq multihop-bfd
+ 60 permit udp any any eq micro-bfd
+ 70 permit udp any any eq sbfd
+ 80 permit udp any eq sbfd any eq sbfd-initiator
+ 90 permit ospf any any
+ 100 permit tcp any any eq ssh telnet www snmp bgp https msdp ldp netconf-ssh gnmi [match 873 packets, 1 day, 20:43:39 ago]
+ 110 permit udp any any eq bootps bootpc snmp rip ntp ldp [match 970 packets, 1:43:38 ago]
+ 120 permit tcp any any eq mlag ttl eq 255
+ 130 permit udp any any eq mlag ttl eq 255
+ 140 permit vrrp any any
+ 150 permit ahp any any
+ 160 permit pim any any
+ 170 permit igmp any any
+ 180 permit tcp any any range 5900 5910
+ 190 permit tcp any any range 50000 50100 [match 1480505 packets, 1 day, 20:43:16 ago]
+ 200 permit udp any any range 51000 51100
+ 210 permit tcp any any eq 3333
+ 220 permit tcp any any eq nat ttl eq 255
+ 230 permit tcp any eq bgp any
+ 240 permit rsvp any any
+ 250 permit tcp any any eq 6040
+ 260 permit tcp any any eq 5541 ttl eq 255
+ 270 permit tcp any any eq 5542 ttl eq 255
+
2. There are multiple ways to quickly edit and remove the unnecessary match
+ outputs, in this example we'll use sed
on EOS. Save the file to /mnt/flash
:
3. Enter bash: #bash
4. Go to /mnt/flash
and remove the match outputs
5. Reading the file now should be clean without all the match counter outputs like below:
+IP Access List default-control-plane-acl
+ counters per-entry
+ 10 permit icmp any any
+ 20 permit ip any any tracked
+ 30 permit udp any any eq bfd ttl eq 255
+ 40 permit udp any any eq bfd-echo ttl eq 254
+ 50 permit udp any any eq multihop-bfd
+ 60 permit udp any any eq micro-bfd
+ 70 permit udp any any eq sbfd
+ 80 permit udp any eq sbfd any eq sbfd-initiator
+ 90 permit ospf any any
+ 100 permit tcp any any eq ssh telnet www snmp bgp https msdp ldp netconf-ssh gnmi
+ 110 permit udp any any eq bootps bootpc snmp rip ntp ldp
+ 120 permit tcp any any eq mlag ttl eq 255
+ 130 permit udp any any eq mlag ttl eq 255
+ 140 permit vrrp any any
+ 150 permit ahp any any
+ 160 permit pim any any
+ 170 permit igmp any any
+ 180 permit tcp any any range 5900 5910
+ 190 permit tcp any any range 50000 50100
+ 200 permit udp any any range 51000 51100
+ 210 permit tcp any any eq 3333
+ 220 permit tcp any any eq nat ttl eq 255
+ 230 permit tcp any eq bgp any
+ 240 permit rsvp any any
+ 250 permit tcp any any eq 6040
+ 260 permit tcp any any eq 5541 ttl eq 255
+ 270 permit tcp any any eq 5542 ttl eq 255
+
6. Now we can just copy that ACLs content into a new ACL, add our new rules and apply it on the control-plane.
+From config mode:
+ip access-list custom-cp
+ <paste the content of the default CP from the file created>
+ 280 permit tcp any any eq 5900
+
7. Apply the new ACL
+Default VRF
+ +Non-default VRF
+ + + + + + + + + +Arista APs include an agent module (ocagent) that implements the OpenConfig +interfaces. The agent module interacts with the rest of the AP modules for +applying changes, fetching data, etc. For mor information on OpenConfig +implementation in Arista WiFi, +see OpenConfig for Arista WiFi.
+This page lists a few examples of the AP using gNMI. For more information on gNxI, refer to gNxI Tools.
+python py_gnmicli.py -m
+get -t <AP-IP> -x /provision-aps -user <username> -pass <password> -p <port> -g -o openconfig.mojonetworks.com
+
+ +
+ + +python py_gnmicli.py -m
+get -t <AP-IP> -user <username> -pass <password> -p <port> -g -o openconfig.mojonetworks.com -x access-points/access-point[hostname=<host>]/ssids/ssid[name=<ssid-name>]/state/operating-frequency
+
python py_gnmicli.py -m
+get -t <AP-IP> -user <username> -pass <password> -p <port> -g -o openconfig.mojonetworks.com -x access-points/access-point[hostname=<host>]/ssids/ssid[name=<ssid-name>]/config
+
+ +
{
+ "openconfig-access-points:dva": true,
+ "openconfig-access-points:supported-data-rates-5g": [
+ "openconfig-wifi-types:RATE_11MB",
+ "openconfig-wifi-types:RATE_12MB",
+ "openconfig-wifi-types:RATE_18MB",
+ "openconfig-wifi-types:RATE_24MB",
+ "openconfig-wifi-types:RATE_36MB",
+ "openconfig-wifi-types:RATE_48MB",
+ "openconfig-wifi-types:RATE_54MB"
+ ],
+ "openconfig-access-points:opmode": "WPA2_PERSONAL",
+ "openconfig-access-points:okc": true,
+ "openconfig-access-points:supported-data-rates-2g": [
+ "openconfig-wifi-types:RATE_11MB",
+ "openconfig-wifi-types:RATE_12MB",
+ "openconfig-wifi-types:RATE_18MB",
+ "openconfig-wifi-types:RATE_24MB",
+ "openconfig-wifi-types:RATE_36MB",
+ "openconfig-wifi-types:RATE_48MB",
+ "openconfig-wifi-types:RATE_54MB"
+ ],
+ "openconfig-access-points:name": "OCWiFi1",
+ "openconfig-access-points:basic-data-rates-2g": [
+ "openconfig-wifi-types:RATE_11MB",
+ "openconfig-wifi-types:RATE_12MB",
+ "openconfig-wifi-types:RATE_18MB",
+ "openconfig-wifi-types:RATE_24MB",
+ "openconfig-wifi-types:RATE_36MB",
+ "openconfig-wifi-types:RATE_48MB",
+ "openconfig-wifi-types:RATE_54MB"
+ ],
+ "openconfig-access-points:wpa2-psk": "0123456789",
+ "openconfig-access-points:basic-data-rates-5g": [
+ "openconfig-wifi-types:RATE_11MB",
+ "openconfig-wifi-types:RATE_12MB",
+ "openconfig-wifi-types:RATE_18MB",
+ "openconfig-wifi-types:RATE_24MB",
+ "openconfig-wifi-types:RATE_36MB",
+ "openconfig-wifi-types:RATE_48MB",
+ "openconfig-wifi-types:RATE_54MB"
+ ]
+}
+
python py_gnmicli.py -m
+get -t <AP-IP> -user <username> -pass <password> -p <port> -g -o openconfig.mojonetworks.com -x access-points/access-point[hostname=<host>]/ssids/ssid[name=<ssid-name>]/clients
+
+ +
{
+ "openconfig-access-points:client": [
+ {
+ "mac": "C2:2F:42:79:CB:BA",
+ "client-rf": {
+ "state": {
+ "phy-rate": 0,
+ "rssi": -52,
+ "frequency": 0,
+ "snr": 42,
+ "ss": 0
+ }
+ },
+ "state": {
+ "mac": "C2:2F:42:79:CB:BA",
+ "counters": {
+ "tx-bytes": "34707",
+ "tx-retries": "0",
+ "rx-bytes": "19705",
+ "rx-retries": "18"
+ }
+ },
+ "client-connection": {
+ "state": {
+ "username": "",
+ "client-state": "openconfig-wifi-types:AUTHENTICATED",
+ "hostname": "",
+ "operating-system": "",
+ "ipv6-addresses": [
+ "fe80::c02f:42ff:fe79:cbba"
+ ],
+ "ipv4-address": [
+ "192.168.29.250"
+ ],
+ "connection-time": "1628849487411018113"
+ }
+ }
+ }
+ ]
+}
+
python py_gnmicli.py -m
+get -t <AP-IP> -user <username> -pass <password> -p <port> -g -o openconfig.mojonetworks.com -x access-points/access-point[hostname=<host>]/radios/radio[id=1][operating-frequency=FREQ_5GHZ]/state/channel
+
+ +
{
+ timestamp: 1628855017049472718
+ update {
+ path {
+ elem {
+ name: "access-points"
+ }
+ elem {
+ name: "access-point"
+ key {
+ key: "hostname"
+ value: "arista"
+ }
+ }
+ elem {
+ name: "radios"
+ }
+ elem {
+ name: "radio"
+ key {
+ key: "id"
+ value: "1"
+ }
+ key {
+ key: "operating-frequency"
+ value: "FREQ_5GHZ"
+ }
+ }
+ elem {
+ name: "state"
+ }
+ elem {
+ name: "channel"
+ }
+ }
+ val {
+ uint_val: 36
+ }
+ }
+}
+
python py_gnmicli.py -m
+get -t <AP-IP> -user <username> -pass <password> -p <port> -g -o openconfig.mojonetworks.com -x access-points/access-point[hostname=<host>]/radios/radio[id=1][operating-frequency=FREQ_5GHZ]/state/transmit-eirp
+
+ +
{
+ timestamp: 1628855017049472718
+ update {
+ path {
+ elem {
+ name: "access-points"
+ }
+ elem {
+ name: "access-point"
+ key {
+ key: "hostname"
+ value: "arista"
+ }
+ }
+ elem {
+ name: "radios"
+ }
+ elem {
+ name: "radio"
+ key {
+ key: "id"
+ value: "1"
+ }
+ key {
+ key: "operating-frequency"
+ value: "FREQ_5GHZ"
+ }
+ }
+ elem {
+ name: "state"
+ }
+ elem {
+ name: "transmit-eirp"
+ }
+ }
+ val {
+ uint_val: 28
+ }
+ }
+}
+
python py_gnmicli.py -m
+set-replace-t <AP-IP> -user <username> -pass <password> -p <port> -g -o openconfig.mojonetworks.com -x access-points/access-point[hostname=<host>]/radios/radio[id=1][operating-frequency=FREQ_5GHZ]/config/channel -val 169
+
+ +
response {
+ path {
+ elem {
+ name: "access-points"
+ }
+ elem {
+ name: "access-point"
+ key {
+ key: "hostname"
+ value: "arista"
+ }
+ }
+ elem {
+ name: "radios"
+ }
+ elem {
+ name: "radio"
+ key {
+ key: "id"
+ value: "1"
+ }
+ key {
+ key: "operating-frequency"
+ value: "FREQ_5GHZ"
+ }
+ }
+ elem {
+ name: "config"
+ }
+ elem {
+ name: "channel"
+ }
+ }
+ op: REPLACE
+}
+
In this ansible collection we show how to use ansible to find all the available +modules within an Arista EOS device using the capabilities method within +gNMI.
+[leaf]
+127.0.0.1 ansible_user=admin ansible_password=admin
+
+[all:vars]
+ansible_user=admin
+ansible_password=admin
+ansible_become_pass=admin
+ansible_python_interpreter=/usr/bin/python3
+ansible_port=6030
+ansible_connection=nokia.grpc.gnmi
+ansible_gnmi_encoding=JSON
+
ok: [10.20.30.67] => {
+ "msg": {
+ "gNMIVersion": "0.7.0",
+ "supportedEncodings": [
+ "JSON",
+ "JSON_IETF",
+ "ASCII"
+ ],
+ "supportedModels": [
+ {
+ "name": "arista-exp-eos-multicast",
+ "organization": "Arista Networks <http://arista.com/>"
+ },
+ {
+ "name": "arista-exp-eos-evpn",
+ "organization": "Arista Networks, Inc."
+ },
+
gnmi -addr 198.51.100.219:6030 -username admin -password arista \
+ get '/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp'`
+
+ +
/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp:
+{
+ "openconfig-network-instance:global": {
+ "confederation": {
+ "config": {
+ "identifier": 0
+ },
+ "state": {p
+ "identifier": 0
+ }
+ },
+ "config": {
+ "as": 4206000022,
+ "router-id": "0.0.0.0"
+ },
+ "default-route-distance": {
+ "config": {
+ "external-route-distance": 200,
+ "internal-route-distance": 200
+ },
+ "state": {
+ "external-route-distance": 200,
+ "internal-route-distance": 200
+ }
+ },
+ "graceful-restart": {
+ "config": {
+ "restart-time": 0
+ },
+ "state": {
+ "restart-time": 0
+ }
+ },
+ "route-selection-options": {
+ "config": {},
+ "state": {}
+ },
+ "state": {
+ "as": 4206000022,
+ "router-id": "4.4.4.4"
+ }
+ },
+ "openconfig-network-instance:neighbors": {
+ "neighbor": [
+ {
+ "afi-safis": {
+ "afi-safi": [
+ {
+ "afi-safi-name": "IPV4_UNICAST",
+ "config": {
+ "afi-safi-name": "IPV4_UNICAST",
+ "enabled": false
+ },
+ "graceful-restart": {
+ "config": {
+ "enabled": false
+ },
+ "state": {
+ "enabled": false
+ }
+ },
+ "state": {
+ "afi-safi-name": "IPV4_UNICAST",
+ "enabled": false
+ }
+ },
+ {
+ "afi-safi-name": "IPV6_UNICAST",
+ "config": {
+ "afi-safi-name": "IPV6_UNICAST",
+ "enabled": false
+ },
+ "graceful-restart": {
+ "config": {
+ "enabled": false
+ },
+ "state": {
+ "enabled": false
+ }
+ },
+ "state": {
+ "afi-safi-name": "IPV6_UNICAST",
+ "enabled": false
+ }
+ }
+ ]
+ },
+ "config": {
+ "auth-password": "",
+ "description": "",
+ "local-as": 0,
+ "neighbor-address": "3.4.5.6",
+ "peer-as": 1,
+ "send-community": "NONE"
+ },
+ "ebgp-multihop": {
+ "config": {
+ "multihop-ttl": 0
+ },
+ "state": {
+ "multihop-ttl": 0
+ }
+ },
+ "neighbor-address": "3.4.5.6",
+ "route-reflector": {
+ "config": {
+ "route-reflector-client": false
+ },
+ "state": {
+ "route-reflector-client": false
+ }
+ },
+ "state": {
+ "auth-password": "",
+ "description": "",
+ "local-as": 0,
+ "peer-as": 1,
+ "send-community": "NONE"
+ },
+ "timers": {
+ "config": {
+ "hold-time": "180.0",
+ "keepalive-interval": "60.0"
+ },
+ "state": {
+ "hold-time": "180.0",
+ "keepalive-interval": "60.0"
+ }
+ },
+ "transport": {
+ "config": {
+ "passive-mode": false
+ },
+ "state": {
+ "passive-mode": false
+ }
+ }
+ },
+ {
+ "afi-safis": {
+ "afi-safi": [
+ {
+ "afi-safi-name": "IPV4_UNICAST",
+ "config": {
+ "afi-safi-name": "IPV4_UNICAST",
+ "enabled": false
+ },
+ "graceful-restart": {
+ "config": {
+ "enabled": false
+ },
+ "state": {
+ "enabled": false
+ }
+ },
+ "state": {
+ "afi-safi-name": "IPV4_UNICAST",
+ "enabled": false
+ }
+ },
+ {
+ "afi-safi-name": "IPV6_UNICAST",
+ "config": {
+ "afi-safi-name": "IPV6_UNICAST",
+ "enabled": false
+ },
+ "graceful-restart": {
+ "config": {
+ "enabled": false
+ },
+ "state": {
+ "enabled": false
+ }
+ },
+ "state": {
+ "afi-safi-name": "IPV6_UNICAST",
+ "enabled": false
+ }
+ }
+ ]
+ },
+ "config": {
+ "auth-password": "",
+ "description": "",
+ "local-as": 0,
+ "neighbor-address": "20.1.1.1",
+ "peer-as": 65001,
+ "send-community": "NONE"
+ },
+ "ebgp-multihop": {
+ "config": {
+ "multihop-ttl": 0
+ },
+ "state": {
+ "multihop-ttl": 0
+ }
+ },
+ "neighbor-address": "20.1.1.1",
+ "route-reflector": {
+ "config": {
+ "route-reflector-client": false
+ },
+ "state": {
+ "route-reflector-client": false
+ }
+ },
+ "state": {
+ "auth-password": "",
+ "description": "",
+ "local-as": 0,
+ "peer-as": 65001,
+ "send-community": "NONE"
+ },
+ "timers": {
+ "config": {
+ "hold-time": "180.0",
+ "keepalive-interval": "60.0"
+ },
+ "state": {
+ "hold-time": "180.0",
+ "keepalive-interval": "60.0"
+ }
+ },
+ "transport": {
+ "config": {
+ "passive-mode": false
+ },
+ "state": {
+ "passive-mode": false
+ }
+ }
+ }
+ ]
+ }
+
gnmi -addr 192.0.2.139 -username admin \
+ get '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors'
+
+ +
/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors:
+{
+ "openconfig-network-instance:neighbor": [
+ {
+ "afi-safis": {
+ "afi-safi": [
+ {
+ "afi-safi-name": "openconfig-bgp-types:IPV6_UNICAST",
+ "config": {
+ "afi-safi-name": "openconfig-bgp-types:IPV6_UNICAST"
+ },
+ "state": {
+ "afi-safi-name": "openconfig-bgp-types:IPV6_UNICAST",
+ "prefixes": {
+ "arista-bgp-augments:best-ecmp-paths": 0,
+ "arista-bgp-augments:best-paths": 0,
+ "installed": 0,
+ "received": 0,
+ "sent": 0
+ }
+ }
+ },
+ {
+ "afi-safi-name": "openconfig-bgp-types:L2VPN_EVPN",
+ "config": {
+ "afi-safi-name": "openconfig-bgp-types:L2VPN_EVPN"
+ },
+ "state": {
+ "afi-safi-name": "openconfig-bgp-types:L2VPN_EVPN",
+ "prefixes": {
+ "arista-bgp-augments:best-ecmp-paths": 0,
+ "arista-bgp-augments:best-paths": 0,
+ "installed": 0,
+ "received": 0,
+ "sent": 0
+ }
+ }
+ },
+ {
+ "afi-safi-name": "openconfig-bgp-types:IPV4_UNICAST",
+ "config": {
+ "afi-safi-name": "openconfig-bgp-types:IPV4_UNICAST"
+ },
+ "state": {
+ "afi-safi-name": "openconfig-bgp-types:IPV4_UNICAST",
+ "prefixes": {
+ "arista-bgp-augments:best-ecmp-paths": 0,
+ "arista-bgp-augments:best-paths": 0,
+ "installed": 0,
+ "received": 0,
+ "sent": 0
+ }
+ }
+ }
+ ]
+ },
+ "apply-policy": {
+ "config": {
+ "default-export-policy": "REJECT_ROUTE",
+ "default-import-policy": "REJECT_ROUTE"
+ },
+ "state": {
+ "default-export-policy": "REJECT_ROUTE",
+ "default-import-policy": "REJECT_ROUTE"
+ }
+ },
+ "as-path-options": {
+ "config": {
+ "replace-peer-as": false
+ },
+ "state": {
+ "replace-peer-as": false
+ }
+ },
+ "config": {
+ "enabled": true,
+ "neighbor-address": "172.168.14.2",
+ "peer-as": 65002,
+ "send-community": "NONE"
+ },
+ "ebgp-multihop": {
+ "config": {
+ "enabled": false,
+ "multihop-ttl": 0
+ },
+ "state": {
+ "enabled": false,
+ "multihop-ttl": 0
+ }
+ },
+ "neighbor-address": "172.168.14.2",
+ "state": {
+ "enabled": true,
+ "established-transitions": "2",
+ "last-established": "1614170027122047488",
+ "messages": {
+ "received": {
+ "UPDATE": "2"
+ },
+ "sent": {
+ "UPDATE": "2"
+ }
+ },
+ "neighbor-address": "172.168.14.2",
+ "peer-as": 65002,
+ "send-community": "NONE",
+ "session-state": "ESTABLISHED"
+ },
+ "transport": {
+ "config": {
+ "mtu-discovery": true
+ },
+ "state": {
+ "mtu-discovery": true,
+ "remote-address": "172.168.14.2",
+ "remote-port": 0
+ }
+ }
+ }
+ ]
+}
+
gnmi -addr 192.0.2.139:6030 -username admin -password arista \
+ get '/interfaces/interface/subinterfaces/subinterface/state/description'
+
/interfaces/interface[name=Ethernet3]/subinterfaces/subinterface[index=0]/state/description: SRV01
+/interfaces/interface[name=Ethernet1]/subinterfaces/subinterface[index=0]/state/description: DCI
+/interfaces/interface[name=Ethernet2]/subinterfaces/subinterface[index=0]/state/description: To Spines
+
gnmi -addr 198.51.100.100:6030 -username admin -password arista \
+ get 'interfaces/interface[name=Ethernet1/1]/subinterfaces/subinterface/state/description'
+
/interfaces/interface[name=Ethernet1/1]/subinterfaces/subinterface[index=0]/state/description: "Tyrion"
+
gnmi -addr 192.0.2.139:6030 -username admin -password arista \
+ get 'interfaces/interface/state/oper-status'`
+
gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get 'interfaces/interface[name=Ethernet24]/state/'`
+
+ +
/interfaces/interface[name=Ethernet24]/state:
+{
+ "openconfig-interfaces:admin-status": "UP",
+ "openconfig-interfaces:counters": {
+ "in-broadcast-pkts": "1",
+ "in-discards": "0",
+ "in-errors": "0",
+ "in-fcs-errors": "0",
+ "in-multicast-pkts": "70143",
+ "in-octets": "570132503174",
+ "in-unicast-pkts": "376128549",
+ "out-broadcast-pkts": "2",
+ "out-discards": "0",
+ "out-errors": "0",
+ "out-multicast-pkts": "169207",
+ "out-octets": "569979193348",
+ "out-unicast-pkts": "376049116"
+ },
+ "openconfig-interfaces:description": "",
+ "openconfig-interfaces:enabled": true,
+ "openconfig-platform-port:hardware-port": "Port24",
+ "openconfig-interfaces:ifindex": 24,
+ "arista-intf-augments:inactive": false,
+ "openconfig-interfaces:last-change": "1614001155863084032",
+ "openconfig-interfaces:loopback-mode": false,
+ "openconfig-interfaces:mtu": 0,
+ "openconfig-interfaces:name": "Ethernet24",
+ "openconfig-interfaces:oper-status": "UP",
+ "openconfig-vlan:tpid": "openconfig-vlan-types:TPID_0X8100",
+ "openconfig-interfaces:type": "iana-if-type:ethernetCsmacd"
+}
+
gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get 'interfaces/interface[name=Ethernet24]/state/oper-status'
+
Output:
+ +gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get 'interfaces/interface[name=Ethernet24]/state/admin-status'`
+
Output:
+ +gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get "components/component/transceiver/physical-channels/channel/state/"
+
gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get "components/component[name=Ethernet24 transceiver]/transceiver/physical-channels/channel/state/"
+
+ +
/components/component[name=Ethernet24 transceiver]/transceiver/physical-channels/channel[index=0]/state:
+{
+ "openconfig-platform-transceiver:index": 0,
+ "openconfig-platform-transceiver:input-power": {
+ "instant": "-0.26"
+ },
+ "openconfig-platform-transceiver:laser-bias-current": {
+ "instant": "7.49"
+ },
+ "openconfig-platform-transceiver:output-power": {
+ "instant": "0.32"
+ }
+}
+
gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get 'components/component/cpu'
+
+ +
/components/component[name=CPU3]/cpu:
+{
+ "openconfig-platform-cpu:utilization": {
+ "state": {
+ "avg": 18,
+ "instant": 16,
+ "interval": "1000000000000",
+ "max": 28,
+ "max-time": "3230106984172745216",
+ "min": 13,
+ "min-time": "3230106514174602752"
+ }
+ }
+}
+/components/component[name=CPU0]/cpu:
+{
+ "openconfig-platform-cpu:utilization": {
+ "state": {
+ "avg": 17,
+ "instant": 16,
+ "interval": "1000000000000",
+ "max": 25,
+ "max-time": "3230106564173730816",
+ "min": 12,
+ "min-time": "3230106394175068672"
+ }
+ }
+}
+/components/component[name=CPU1]/cpu:
+{
+ "openconfig-platform-cpu:utilization": {
+ "state": {
+ "avg": 18,
+ "instant": 17,
+ "interval": "1000000000000",
+ "max": 27,
+ "max-time": "3230107464174793728",
+ "min": 13,
+ "min-time": "3230107334172570624"
+ }
+ }
+}
+/components/component[name=CPU2]/cpu:
+{
+ "openconfig-platform-cpu:utilization": {
+ "state": {
+ "avg": 17,
+ "instant": 21,
+ "interval": "1000000000000",
+ "max": 24,
+ "max-time": "3230106924173756928",
+ "min": 11,
+ "min-time": "3230107394173572608"
+ }
+ }
+}
+
gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get 'components/component/state/memory/'
+
Output:
+/components/component[name=Chassis]/state/memory:
+{
+ "openconfig-platform:available": "8298774528",
+ "openconfig-platform:utilized": "7706267648"
+}
+
gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ get 'components/component/state/temperature/instant'
+
+ +
/components/component[name=DomTemperatureSensor49]/state/temperature/instant: 30.49609375
+/components/component[name=DomTemperatureSensor25]/state/temperature/instant: 24.69921875
+/components/component[name=DomTemperatureSensor40]/state/temperature/instant: 25.5078125
+/components/component[name=TempSensorP2/2]/state/temperature/instant: 0.0
+/components/component[name=TempSensorP1/3]/state/temperature/instant: 40.0
+/components/component[name=TempSensorP2/1]/state/temperature/instant: 0.0
+/components/component[name=TempSensorP2/3]/state/temperature/instant: 0.0
+/components/component[name=DomTemperatureSensor24]/state/temperature/instant: 24.5
+/components/component[name=DomTemperatureSensor26]/state/temperature/instant: 23.73046875
+/components/component[name=DomTemperatureSensor54]/state/temperature/instant: 27.26953125
+/components/component[name=TempSensorP1/1]/state/temperature/instant: 34.0
+/components/component[name=DomTemperatureSensor50]/state/temperature/instant: 27.453125
+/components/component[name=TempSensorP1/2]/state/temperature/instant: 25.0
+/components/component[name=TempSensor1]/state/temperature/instant: 45.84278576588521
+/components/component[name=TempSensor15]/state/temperature/instant: 33.875
+/components/component[name=TempSensor18]/state/temperature/instant: 44.625
+/components/component[name=TempSensor16]/state/temperature/instant: 22.75
+/components/component[name=TempSensor17]/state/temperature/instant: 37.0
+/components/component[name=TempSensor14]/state/temperature/instant: 37.0
+
To get EOS native paths, OCTA has to be enabled as mentioned in the
+configuration section. Performing GET/SUBSCRIBE actions using EOS native paths
+require changing the origin to eos_native
.
/Smash/bridging/status/smashFdbStatus
/Smash/arp/status/arpEntry
/Smash/arp/status/neighborEntry
/Smash/routing/status/route
/Smash/routing6/status/route
/Smash/routing/status/nexthop
/Smash/routing6/status/nexthop
/Kernel/proc/cpu
/Kernel/proc/stat
/Kernel/sysinfo
/Eos/image
/Smash/counters/ethIntf/<agent>/current/counter
<agent>
are:SandCounters
StrataCounters
Strata-FixedSystem
or
+ StrataCounters
from 4.22+FocalPointV2
XpCounters
BfnCounters
gnmi -addr 192.0.2.130:6030 -username admin \
+ get origin=eos_native '/Kernel/proc/cpu/utilization/total'
+
Output:
+/Kernel/proc/cpu/utilization/total/nice:
+38446
+/Kernel/proc/cpu/utilization/total/system:
+2347714
+/Kernel/proc/cpu/utilization/total/idle:
+247720286
+/Kernel/proc/cpu/utilization/total/name:
+total
+/Kernel/proc/cpu/utilization/total/util:
+7
+/Kernel/proc/cpu/utilization/total/user:
+16984784
+
gnmi -addr 192.0.2.130:6030 -username admin get origin=eos_native \
+ 'Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32'`
+
+ +
/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/temperature:
+{
+ "value": 32.5
+}
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/maxTemperature:
+{
+ "value": 34.88671875
+}
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/maxTemperatureTime: 1564757444.339129
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/name: DomTemperatureSensor32
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/generationId: 0
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/hwStatus: ok
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/alertRaised: false
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/alertRaisedCount: 0
+/Sysdb/environment/archer/temperature/status/system/DomTemperatureSensor32/lastAlertRaisedTime: 1564194739.259879
+
gnmi -addr 192.0.2.139:6030 -username admin get origin=eos_native '/Sysdb/connectivityMonitor/status/hostStatus/'
+
+ +
/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/key/hostName: wls100
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/key/vrfName:
+{
+ "value": "default"
+}
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/name: wls100_default
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/defaultStats/packetLoss: 0
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/defaultStats/httpResponseTime: 0
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/defaultStats/interfaceName:
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/defaultStats/jitter: 0
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/defaultStats/latency: 0
+/Sysdb/connectivityMonitor/status/hostStatus/wls100_default/ipAddr: "192.0.2.140"
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/key/hostName: ats323
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/key/vrfName:
+{
+ "value": "management"
+}
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/name: ats323_management
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/ipAddr: "192.0.2.138"
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/defaultStats/latency: 0.127
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/defaultStats/jitter: 0.033
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/defaultStats/packetLoss: 0
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/defaultStats/httpResponseTime: 21.860306
+/Sysdb/connectivityMonitor/status/hostStatus/ats323_management/defaultStats/interfaceName:
+
gnmi -addr 192.0.2.139:6030 -username cvpadmin -password arista \
+ update '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]' \
+ '{"config": {"neighbor-address":"198.51.100.43", "peer-as": 123}}'
+
gnmi -addr 192.0.2.203:6030 -username arista -password arista
+ update '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]' \
+ {"config": {"neighbor-address":"198.51.100.43", "peer-as": 123, "enabled": true, "send-community": "EXTENDED"}}'
+
gnmi -addr 192.0.2.203 -username arista -password arista update \
+ '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/peer-groups/peer-group[peer-group-name=XYZ]' \
+ '{"config": {"peer-group-name":"XYZ", "local-as": 114}}'
+
gnmi -addr 192.0.2.203:6030 -username arista -password arista \
+ update '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.0]/config/peer-as' \
+ '110'
+
gnmi -addr 192.0.2.203:6030 -username arista -password arista \
+ update '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.0]' \
+ '{"config": {"peer-as": 110}}'
+
gnmi -addr 192.0.2.203:6030 -username arista -password arista \
+ update '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]/config/peer-group' \
+ 'XYZ'
+
gnmi -addr 192.0.2.203:6030 -username arista -password arista \
+ update '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.0]' \
+ '{"config": {"peer-group": "XYZ","peer-as": 143}}'
+
gnmi -addr 192.0.2.203:6030 -username arista -password arista \
+ update '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp' bgp.json
+
+ +
{
+ "neighbors": {
+ "neighbor": [
+ {
+ "config": {
+ "enabled": true,
+ "neighbor-address": "10.10.10.154",
+ "peer-group": "XYZ"
+ },
+ "neighbor-address": "10.10.10.154"
+ },
+ {
+ "config": {
+ "enabled": true,
+ "neighbor-address": "10.10.10.157",
+ "peer-group": "XYZ"
+ },
+ "neighbor-address": "10.10.10.157"
+ }
+ ]
+ },
+ "peer-groups": {
+ "peer-group": [
+ {
+ "config": {
+ "peer-as": 65002,
+ "peer-group-name": "ABC"
+ },
+ "peer-group-name": "ABC"
+ }
+ ]
+ }
+}
+
+ +
{
+ "acl-set": [
+ {
+ "config": {
+ "name": "test",
+ "type": "ACL_IPV4"
+ },
+ "name": "test",
+ "type": "ACL_IPV4",
+ "acl-entries": {
+ "acl-entry": [
+ {
+ "sequence-id": 10,
+ "actions": {
+ "config": {
+ "forwarding-action": "DROP"
+ }
+ },
+ "config": {
+ "sequence-id": 10
+ },
+ "ipv4": {
+ "config": {
+ "destination-address": "192.0.2.1/32",
+ "source-address": "0.0.0.0/0"
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
+
This creates
+ +gnmi -addr 192.0.2.139:6030 -username arista -password arista \
+ update '/interfaces/interface[name=Ethernet1]/config/enabled' \
+ 'false'
+
gnmi -addr 192.0.2.139:6030 -username arista -password arista \
+ update '/interfaces/interface[name=Ethernet1]/config/enabled' \
+ 'true'
+
gnmi -addr 192.0.2.203 -username arista -password arista \
+ subscribe '/network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state'
+
gnmi -addr 192.0.2.203 -username arista -password arista \
+ subscribe '/network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor[neighbor-address=198.51.100.5]/state'
+
gnmi -addr 192.0.2.214:6030 -username admin -password arista \
+ -sample_interval 5s -stream_mode sample \
+ subscribe \
+ '/network-instances/network-instance[name=Tenant_A_WEB_Zone]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.1]/afi-safis/afi-safi[afi-safi-name=openconfig-bgp-types:IPV4_UNICAST]/state/prefixes/received'
+
gnmi -addr 192.0.2.214:6030 -username arista -password arista \
+ update origin=cli "" "router bgp 65101
+ neighbor IPv4-UNDERLAY-PEERS maximum-routes 12500"
+
++NOTE the
+neighbor
command has to be on a new line, so the previous line should not end in\
.
+ +
/show version:
+{
+ "architecture": "i686",
+ "bootupTimestamp": 1626291561.0,
+ "configMacAddress": "00:00:00:00:00:00",
+ "hardwareRevision": "",
+ "hwMacAddress": "00:00:00:00:00:00",
+ "imageFormatVersion": "1.0",
+ "internalBuildId": "ed275a6c-1771-482d-829b-125e9c6ba677",
+ "internalVersion": "4.26.2F-23035564.riorel",
+ "isIntlVersion": false,
+ "memFree": 2422124,
+ "memTotal": 4002356,
+ "mfgName": "Arista",
+ "modelName": "vEOS-lab",
+ "serialNumber": "BAD032986065E8DC14CBB6472EC314A6",
+ "systemMacAddress": "50:08:00:a7:ca:c3",
+ "uptime": 1814877.63,
+ "version": "4.26.2F-23035564.riorel (engineering build)"
+}
+
To run show commands that are not converted to JSON and require format="text"
the ASCII
encoding
+can be used from EOS 4.29.2F or newer.
gnmi -addr 192.0.2.214:6030 -username cvpadmin -password arista get encoding=ascii origin=cli "show platform fap interrupts"
+
+ +
/show platform fap interrupts:
+ Jericho0
+ --------------------------------------------------------------------------------------------------------------
+ | Interrupt Bit | Count | First Occurrence | Last Occurrence |
+ --------------------------------------------------------------------------------------------------------------
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_12[0] | 55 | 2023-10-05 00:02:22 | 2023-10-20 10:29:21 |
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_13[0] | 39 | 2023-10-05 00:02:21 | 2023-10-16 19:00:15 |
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_14[0] | 39 | 2023-10-05 00:02:23 | 2023-10-16 19:00:15 |
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_15[0] | 39 | 2023-10-05 00:02:22 | 2023-10-16 19:00:15 |
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_20[0] | 67 | 2023-10-05 00:02:26 | 2023-10-24 00:44:24 |
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_21[0] | 56 | 2023-10-05 00:02:25 | 2023-10-24 00:44:24 |
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_22[0] | 53 | 2023-10-05 00:02:25 | 2023-10-24 00:45:15 |
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_23[0] | 55 | 2023-10-05 00:02:24 | 2023-10-24 00:45:15 |
+ | IPS_QueueEnteredDel[1] | 6 | 2023-10-11 14:00:20 | 2023-10-11 14:12:02 |
+ | EPNI_PP_NewDaErr[0] | 255206 | 2023-10-05 15:06:43 | 2023-10-25 21:42:04 |
+ | EPNI_PP_VsiMembershipDeny[1] | 2 | 2023-10-11 02:27:16 | 2023-10-11 14:11:46 |
+ | EPNI_PP_EesLastActionNotAc[0] | 255206 | 2023-10-05 15:06:43 | 2023-10-25 21:42:04 |
+ | EPNI_PP_EesLastActionNotAc[1] | 47299 | 2023-10-05 13:33:12 | 2023-10-23 16:16:04 |
+ | FMAC_FMAC_2_RxLostOfSync_0[32] | 883547 | 2023-10-05 00:02:34 | 2023-10-25 21:42:08 |
+<ommitted>
+}
+
The following examples are used to find openconfig paths within Arista EOS using
+the gNMIC binary. There will be some commands which
+will specify one liners which will have the address of the gNMI target and some
+commands which will use the .gnmic.yaml
file which will have the target
+information inside declared. All outputs will be redirected to the outputs file
+with the .json extension so they are easier to view within a text editor.
To install run:
+ +To get the version run:
+ +Output:
+version : 0.27.0
+ commit : cc5759c
+ date : 2022-10-10T06:40:26Z
+ gitURL : https://github.com/openconfig/gnmic
+ docs : https://gnmic.openconfig.net
+
management api gnmi
+ transport grpc default
+ no shutdown
+ provider eos-native
+
+ceos3# show management api gnmi
+Octa: enabled
+Enabled: Yes
+Server: running on port 6030
+SSL Profile: none
+QoS DSCP: none
+Authorization Required:No
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure capabilities \
+ >> outputs/capabilities.json
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ '/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp'
+
gnmic -a 192.0.2.139:6030 -u cvpadmin -p arista --insecure get --path \
+ '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors'
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ '/interfaces/interface/subinterfaces/subinterface/state/description'
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'interfaces/interface[name=Ethernet1]/subinterfaces/subinterface/state/description'
+
[
+ {
+ "timestamp": 1626293671204274106,
+ "time": "2021-07-14T21:14:31.204274106+01:00",
+ "updates": [
+ {
+ "Path": "interfaces/interface[name=Ethernet1]/subinterfaces/subinterface[index=0]/state/description",
+ "values": {
+ "interfaces/interface/subinterfaces/subinterface/state/description": "To-SPINE1"
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'interfaces/interface/state/oper-status'
+
+ +
[
+ {
+ "timestamp": 1626293641102904713,
+ "time": "2021-07-14T21:14:01.102904713+01:00",
+ "updates": [
+ {
+ "Path": "interfaces/interface[name=Management1]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ },
+ {
+ "Path": "interfaces/interface[name=Ethernet1]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ },
+ {
+ "Path": "interfaces/interface[name=Ethernet5]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ },
+ {
+ "Path": "interfaces/interface[name=Ethernet4]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ },
+ {
+ "Path": "interfaces/interface[name=Ethernet3]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ },
+ {
+ "Path": "interfaces/interface[name=Ethernet2]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ },
+ {
+ "Path": "interfaces/interface[name=Port-Channel4]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ },
+ {
+ "Path": "interfaces/interface[name=Port-Channel3]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'interfaces/interface[name=Ethernet1]/state/'
+
+ +
[[
+ {
+ "timestamp": 1626293429376469348,
+ "time": "2021-07-14T21:10:29.376469348+01:00",
+ "updates": [
+ {
+ "Path": "interfaces/interface[name=Ethernet1]/state",
+ "values": {
+ "interfaces/interface/state": {
+ "arista-intf-augments:inactive": false,
+ "openconfig-interfaces:admin-status": "UP",
+ "openconfig-interfaces:counters": {
+ "in-broadcast-pkts": "0",
+ "in-discards": "0",
+ "in-errors": "0",
+ "in-fcs-errors": "0",
+ "in-multicast-pkts": "48",
+ "in-octets": "111398",
+ "in-unicast-pkts": "1460",
+ "out-broadcast-pkts": "1",
+ "out-discards": "0",
+ "out-errors": "0",
+ "out-multicast-pkts": "49",
+ "out-octets": "117389",
+ "out-unicast-pkts": "1457"
+ },
+ "openconfig-interfaces:description": "To-SPINE1",
+ "openconfig-interfaces:ifindex": 1,
+ "openconfig-interfaces:last-change": "1626292006733589760",
+ "openconfig-interfaces:mtu": 0,
+ "openconfig-interfaces:name": "Ethernet1",
+ "openconfig-interfaces:oper-status": "UP",
+ "openconfig-interfaces:type": "iana-if-type:ethernetCsmacd",
+ "openconfig-platform-port:hardware-port": "Port1"
+ }
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'interfaces/interface[name=Ethernet24]/state/oper-status'
+
[
+ {
+ "timestamp": 1626293414057239130,
+ "time": "2021-07-14T21:10:14.05723913+01:00",
+ "updates": [
+ {
+ "Path": "interfaces/interface[name=Ethernet2]/state/oper-status",
+ "values": {
+ "interfaces/interface/state/oper-status": "UP"
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'interfaces/interface[name=Ethernet1]/state/admin-status'
+
[
+ {
+ "timestamp": 1626293085257457373,
+ "time": "2021-07-14T21:04:45.257457373+01:00",
+ "updates": [
+ {
+ "Path": "interfaces/interface[name=Ethernet1]/state/admin-status",
+ "values": {
+ "interfaces/interface/state/admin-status": "UP"
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ "components/component/transceiver/physical-channels/channel/state/"
+
+ +
[
+ {
+ "timestamp": 1626293085257457373,
+ "time": "2021-07-14T21:04:45.257457373+01:00",
+ "updates": [
+ {
+ "Path": "components/component[name=Ethernet49 transceiver]/transceiver/physical-channels/channel[index=0]/state",
+ "values": {
+ "components/component/transceiver/physical-channels/channel/state": {
+ "openconfig-platform-transceiver:index": 0,
+ "openconfig-platform-transceiver:input-power": {
+ "instant": "1.15"
+ },
+ "openconfig-platform-transceiver:laser-bias-current": {
+ "instant": "0.0"
+ },
+ "openconfig-platform-transceiver:output-power": {}
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=Ethernet50 transceiver]/transceiver/physical-channels/channel[index=0]/state",
+ "values": {
+ "components/component/transceiver/physical-channels/channel/state": {
+ "openconfig-platform-transceiver:index": 0,
+ "openconfig-platform-transceiver:input-power": {
+ "instant": "1.11"
+ },
+ "openconfig-platform-transceiver:laser-bias-current": {
+ "instant": "0.0"
+ },
+ "openconfig-platform-transceiver:output-power": {}
+ }
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ "components/component[name=Ethernet49 transceiver]/transceiver/physical-channels/channel/state/"
+
+ +
[
+ {
+ "time": "1970-01-01T01:00:00+01:00",
+ "updates": [
+ {
+ "Path": "components/component[name=Ethernet49 transceiver]/transceiver/physical-channels/channel[index=0]/state",
+ "values": {
+ "components/component/transceiver/physical-channels/channel/state": {
+ "openconfig-platform-transceiver:index": 0,
+ "openconfig-platform-transceiver:input-power": {
+ "instant": "1.08"
+ },
+ "openconfig-platform-transceiver:laser-bias-current": {
+ "instant": "0.0"
+ },
+ "openconfig-platform-transceiver:output-power": {}
+ }
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'components/component/cpu'
+
+ +
[
+ {
+ "timestamp": 1626294810779644595,
+ "time": "2021-07-14T21:33:30.779644595+01:00",
+ "updates": [
+ {
+ "Path": "components/component[name=CPU1]/cpu",
+ "values": {
+ "components/component/cpu": {
+ "openconfig-platform-cpu:utilization": {
+ "state": {
+ "avg": 6,
+ "instant": 6,
+ "interval": "1000000000000",
+ "max": 14,
+ "max-time": "3252585270429488128",
+ "min": 2,
+ "min-time": "3252586330424618496"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=CPU0]/cpu",
+ "values": {
+ "components/component/cpu": {
+ "openconfig-platform-cpu:utilization": {
+ "state": {
+ "avg": 5,
+ "instant": 7,
+ "interval": "1000000000000",
+ "max": 13,
+ "max-time": "3252586170423993344",
+ "min": 1,
+ "min-time": "3252585340433252352"
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'components/component/state/memory/'
+
[
+ {
+ "timestamp": 1626294846423115892,
+ "time": "2021-07-14T21:34:06.423115892+01:00",
+ "updates": [
+ {
+ "Path": "components/component[name=Chassis]/state/memory",
+ "values": {
+ "components/component/state/memory": {
+ "openconfig-platform:available": "4098412544",
+ "openconfig-platform:utilized": "4018016256"
+ }
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'components/component/state/temperature/instant'
+
+ +
[
+ {
+ "timestamp": 1626294876186613578,
+ "time": "2021-07-14T21:34:36.186613578+01:00"
+ "updates": [
+ {
+ "Path": "components/component[name=DomTemperatureSensor50]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 2709375,
+ "precision": 5
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=DomTemperatureSensor49]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 27140625,
+ "precision": 6
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor7]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 41168000000000006,
+ "precision": 15
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor8]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 4225279999999998,
+ "precision": 14
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor9]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 4062560000000002,
+ "precision": 14
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor1]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 39141723894742796,
+ "precision": 15
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor6]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 23875,
+ "precision": 3
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor3]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 21
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor4]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 1725,
+ "precision": 2
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor5]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 29
+ }
+ }
+ },
+ {
+ "Path": "components/component[name=TempSensor2]/state/temperature/instant",
+ "values": {
+ "components/component/state/temperature/instant": {
+ "digits": 32
+ }
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ '/telemetry-system/subscriptions'
+
+ +
[
+ {
+ "source": "192.0.2.214:6030",
+ "timestamp": 1723202310565051604,
+ "time": "2024-08-09T16:48:30.565051604+05:30",
+ "updates": [
+ {
+ "Path": "telemetry-system/subscriptions",
+ "values": {
+ "telemetry-system/subscriptions": {
+ "openconfig-telemetry:dynamic-subscriptions": {
+ "dynamic-subscription": [
+ {
+ "id": "2",
+ "sensor-paths": {
+ "sensor-path": [
+ {
+ "path": "/components/component/state/memory",
+ "state": {
+ "path": "/components/component/state/memory"
+ }
+ },
+ {
+ "path": "/Kernel/proc/cpu/utilization/total",
+ "state": {
+ "path": "/Kernel/proc/cpu/utilization/total"
+ }
+ }
+ ]
+ },
+ "state": {
+ "destination-address": "192.0.2.139",
+ "destination-port": 51478,
+ "encoding": "openconfig-telemetry-types:ENC_PROTO3",
+ "id": "2",
+ "protocol": "openconfig-telemetry-types:STREAM_GRPC"
+ }
+ },
+ {
+ "id": "3",
+ "sensor-paths": {
+ "sensor-path": [
+ {
+ "path": "/components/component/transceiver/physical-channels/channel/state",
+ "state": {
+ "path": "/components/component/transceiver/physical-channels/channel/state"
+ }
+ }
+ ]
+ },
+ "state": {
+ "destination-address": "192.168.3.2",
+ "destination-port": 57928,
+ "encoding": "openconfig-telemetry-types:ENC_PROTO3",
+ "id": "3",
+ "protocol": "openconfig-telemetry-types:STREAM_GRPC"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip subscribe --path \
+ '/network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state'
+
+ +
{
+ "source": "192.0.2.214:6030",
+ "subscription-name": "default-1626302647",
+ "timestamp": 1626292010055258009,
+ "time": "2021-07-14T20:46:50.055258009+01:00",
+ "updates": [
+ {
+ "Path": "network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=172.18.255.42]/state/messages/sent/UPDATE",
+ "values": {
+ "network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state/messages/sent/UPDATE": 8
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.214:6030",
+ "subscription-name": "default-1626302647",
+ "timestamp": 1626292008053994815,
+ "time": "2021-07-14T20:46:48.053994815+01:00",
+ "updates": [
+ {
+ "Path": "network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=172.18.255.42]/state/established-transitions",
+ "values": {
+ "network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state/established-transitions": 1
+ }
+ }
+ ]
+}
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip subscribe --path \
+ 'network-instances/network-instance[name=Tenant_A_WEB_Zone]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.21]/state'
+
+ +
{
+ "source": "192.0.2.214:6030",
+ "subscription-name": "default-1626303017",
+ "timestamp": 1626302991598465536,
+ "time": "2021-07-14T23:49:51.598465536+01:00",
+ "updates": [
+ {
+ "Path": "network-instances/network-instance[name=Tenant_A_WEB_Zone]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.21]/state/last-established",
+ "values": {
+ "network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state/last-established": 1626302991563603200
+ }
+ }
+ ]
+}
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip --sample-interval 5s --stream-mode sample subscribe --path \
+ '/network-instances/network-instance[name=Tenant_A_WEB_Zone]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.21]/afi-safis/afi-safi[afi-safi-name=openconfig-bgp-types:IPV4_UNICAST]/state/prefixes/received'
+
+ +
{
+ "source": "192.0.2.214:6030",
+ "subscription-name": "default-1626303393",
+ "timestamp": 1626303158135414182,
+ "time": "2021-07-14T23:52:38.135414182+01:00",
+ "updates": [
+ {
+ "Path": "network-instances/network-instance[name=Tenant_A_WEB_Zone]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.21]/afi-safis/afi-safi[afi-safi-name=IPV4_UNICAST]/state/prefixes/received",
+ "values": {
+ "network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/received": 5
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.214:6030",
+ "subscription-name": "default-1626303393",
+ "timestamp": 1626303158135414182,
+ "time": "2021-07-14T23:52:38.135414182+01:00",
+ "updates": [
+ {
+ "Path": "network-instances/network-instance[name=Tenant_A_WEB_Zone]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.21]/afi-safis/afi-safi[afi-safi-name=IPV4_UNICAST]/state/prefixes/received",
+ "values": {
+ "network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/received": 5
+ }
+ }
+ ]
+}
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure subscribe --path \
+ "/interfaces/interface/state/counters" >> outputs/interface_state.json
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip set \
+--update-path '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]' \
+--update-file value.json
+
value.json:
+ +Output:
+{
+ "timestamp": 1626305876151537555,
+ "time": "2021-07-15T00:37:56.151537555+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]"
+ }
+ ]
+}
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip set \
+--update-path '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]' \
+--update-file value.json
+
value.json:
+{"config": {"neighbor-address":"198.51.100.43", "peer-as": 123, "enabled": true, "send-community": "EXTENDED"}}
+
Output:
+{
+ "timestamp": 1626305480401353997,
+ "time": "2021-07-15T00:31:20.401353997+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]"
+ }
+ ]
+}
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip set \
+ --update-path '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/peer-groups/peer-group[peer-group-name=XYZ]' \
+ --update-file value.json
+
value.json:
+ +gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip set \
+--update-path '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]/config/peer-as' \
+--update-value '110'
+
Output:
+{
+ "timestamp": 1626306067189329813,
+ "time": "2021-07-15T00:41:07.189329813+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]/config/peer-as"
+ }
+ ]
+}
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip set \
+--update-path '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]/config/peer-group' \
+--update-value 'XYZ'
+
Output:
+{
+ "timestamp": 1626306067189329813,
+ "time": "2021-07-15T00:41:07.189329813+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp/neighbors/neighbor[neighbor-address=198.51.100.43]/config/peer-as"
+ }
+ ]
+}
+
gnmic -a 192.0.2.108:6030 -u cvpadmin -p arista --insecure --gzip set \
+--update-path /acl/acl-sets \
+--update-file acl2.json
+
Output:
+{
+ "timestamp": 1626307972085688242,
+ "time": "2021-07-15T01:12:52.085688242+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "acl/acl-sets"
+ }
+ ]
+}
+
+ +
{
+ "acl-set": [
+ {
+ "config": {
+ "name": "test",
+ "type": "ACL_IPV4"
+ },
+ "name": "test",
+ "type": "ACL_IPV4",
+ "acl-entries": {
+ "acl-entry": [
+ {
+ "sequence-id": 10,
+ "actions": {
+ "config": {
+ "forwarding-action": "DROP"
+ }
+ },
+ "config": {
+ "sequence-id": 10
+ },
+ "ipv4": {
+ "config": {
+ "destination-address": "192.0.2.0/24",
+ "source-address": "0.0.0.0/0"
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
+
This creates
+ +gnmic -a 192.0.2.108:6030 -u cvpadmin -p arista --insecure --gzip set \
+--update-path '/interfaces/interface[name=Ethernet1]/config/enabled' \
+--update-value 'false'
+
{
+ "timestamp": 1626309145489047571,
+ "time": "2021-07-15T01:32:25.489047571+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "interfaces/interface[name=Ethernet1]/config/enabled"
+ }
+ ]
+}
+
gnmic -a 192.0.2.108:6030 -u cvpadmin -p arista --insecure --gzip set \
+--update-path '/interfaces/interface[name=Ethernet1]/config/enabled' \
+--update-value 'true'
+
{
+ "timestamp": 1626309156607307596,
+ "time": "2021-07-15T01:32:36.607307596+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "interfaces/interface[name=Ethernet1]/config/enabled"
+ }
+ ]
+}
+
To get EOS native paths, OCTA has to be enabled as mentioned in the
+configuration section. Performing GET/SUBSCRIBE actions using EOS native paths
+require changing the origin to eos_native
.
/Smash/bridging/status/smashFdbStatus
/Smash/arp/status/arpEntry
/Smash/arp/status/neighborEntry
/Smash/routing/status/route
/Smash/routing6/status/route
/Smash/routing/status/nexthop
/Smash/routing6/status/nexthop
/Kernel/proc/cpu
/Kernel/proc/stat
/Kernel/sysinfo
/Eos/image
/Smash/counters/ethIntf/<agent>/current/counter
<agent>
are:SandCounters
StrataCounters
Strata-FixedSystem
or
+ StrataCounters
from 4.22+FocalPointV2
XpCounters
BfnCounters
gnmic -a 192.0.2.108:6030 -u cvpadmin -p arista --insecure --gzip get --path \
+ 'eos_native:/Kernel/proc/cpu/utilization/total'
+
+ +
[
+ {
+ "timestamp": 1626291721294738334,
+ "time": "2021-07-14T20:42:01.294738334+01:00",
+ "prefix": "eos_native:Kernel/proc/cpu/utilization/total",
+ "updates": [
+ {
+ "Path": "name",
+ "values": {
+ "name": "total"
+ }
+ },
+ {
+ "Path": "nice",
+ "values": {
+ "nice": 28845
+ }
+ },
+ {
+ "Path": "util",
+ "values": {
+ "util": 41
+ }
+ },
+ {
+ "Path": "user",
+ "values": {
+ "user": 32058347
+ }
+ },
+ {
+ "Path": "system",
+ "values": {
+ "system": 4597389
+ }
+ },
+ {
+ "Path": "idle",
+ "values": {
+ "idle": 76373566
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure --gzip get --path \
+ eos_native:/Sysdb/hardware/archer/xcvr/status >> outputs/doms.json
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure --gzip get \
+ --path eos_native:/Eos/image >> outputs/eos_image.json
+
In addition to Octa, LANZ and LANZ Data Streaming also needs to be enabled on the switch.
+ +With Octa and LANZ Data Streaming enabled, LANZ metrics can be subscribed to:
+gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure --gzip \
+ subscribe --path 'eos_native:/LANZ'
+
+ +
{
+ "source": "192.0.2.1:6030",
+ "subscription-name": "default-1669906007",
+ "timestamp": 1669903438845029161,
+ "time": "2022-12-01T19:33:58.845029161+05:30",
+ "prefix": "eos_native:LANZ/config",
+ "updates": [
+ {
+ "Path": "name",
+ "values": {
+ "name": "config"
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.1:6030",
+ "subscription-name": "default-1669906007",
+ "timestamp": 1669903438845141433,
+ "time": "2022-12-01T19:33:58.845141433+05:30",
+ "prefix": "eos_native:LANZ/globalBufferUsage",
+ "updates": [
+ {
+ "Path": "name",
+ "values": {
+ "name": "globalBufferUsage"
+ }
+ },
+ {
+ "Path": "globalBufferUsageRecord",
+ "values": {
+ "globalBufferUsageRecord": {
+ "bufferSize": 0,
+ "duration": 0,
+ "entryType": "",
+ "timestamp": 0
+ }
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.1:6030",
+ "subscription-name": "default-1669906007",
+ "timestamp": 1669906008617947980,
+ "time": "2022-12-01T20:16:48.61794798+05:30",
+ "prefix": "eos_native:LANZ/congestion",
+ "updates": [
+ {
+ "Path": "congestionRecord",
+ "values": {
+ "congestionRecord": {
+ "entryType": "POLLING",
+ "fabricPeerIntfName": "",
+ "intfName": "Ethernet6",
+ "portID": 105,
+ "qDropCount": 0,
+ "queueSize": 1998240,
+ "switchID": 0,
+ "timeOfMaxQLen": 0,
+ "timestamp": 1669906008617720,
+ "trafficClass": 1,
+ "txLatency": 0
+ }
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.1:6030",
+ "subscription-name": "default-1669906007",
+ "timestamp": 1669903438845107943,
+ "time": "2022-12-01T19:33:58.845107943+05:30",
+ "prefix": "eos_native:LANZ/congestion",
+ "updates": [
+ {
+ "Path": "name",
+ "values": {
+ "name": "congestion"
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.1:6030",
+ "subscription-name": "default-1669906007",
+ "timestamp": 1669905829532672732,
+ "time": "2022-12-01T20:13:49.532672732+05:30",
+ "prefix": "eos_native:LANZ/config/portConfigRecord",
+ "updates": [
+ {
+ "Path": "Ethernet6/intfName",
+ "values": {
+ "Ethernet6/intfName": "Ethernet6"
+ }
+ },
+ {
+ "Path": "Ethernet6/switchID",
+ "values": {
+ "Ethernet6/switchID": 0
+ }
+ },
+ {
+ "Path": "Ethernet6/portID",
+ "values": {
+ "Ethernet6/portID": 105
+ }
+ },
+ {
+ "Path": "Ethernet6/internalPort",
+ "values": {
+ "Ethernet6/internalPort": false
+ }
+ },
+ {
+ "Path": "Ethernet6/highThreshold",
+ "values": {
+ "Ethernet6/highThreshold": 40962
+ }
+ },
+ {
+ "Path": "Ethernet6/lowThreshold",
+ "values": {
+ "Ethernet6/lowThreshold": 10241
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.1:6030",
+ "subscription-name": "default-1669906007",
+ "timestamp": 1669905829532649815,
+ "time": "2022-12-01T20:13:49.532649815+05:30",
+ "prefix": "eos_native:LANZ/config",
+ "updates": [
+ {
+ "Path": "configRecord",
+ "values": {
+ "configRecord": {
+ "globalUsageHighThreshold": 0,
+ "globalUsageLowThreshold": 0,
+ "globalUsageReportingEnabled": true,
+ "lanzVersion": 1,
+ "maxQueueSize": 524288000,
+ "numOfPorts": 121,
+ "segmentSize": 16,
+ "timestamp": 1669905829532490
+ }
+ }
+ }
+ ]
+}
+{
+ "source": "192.0.2.1:6030",
+ "subscription-name": "default-1669906007",
+ "timestamp": 1669903438845176033,
+ "time": "2022-12-01T19:33:58.845176033+05:30",
+ "prefix": "eos_native:LANZ/error",
+ "updates": [
+ {
+ "Path": "name",
+ "values": {
+ "name": "error"
+ }
+ },
+ {
+ "Path": "errorRecord",
+ "values": {
+ "errorRecord": {
+ "errorMessage": "",
+ "timestamp": 0
+ }
+ }
+ }
+ ]
+}
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure get \
+ --path "cli:/show running-config" >> outputs/outputs.json
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure get \
+ --path "cli:/show ip route summary" \
+ | jq '.[0].updates[0].values."show ip route summary".totalRoutes'
+
There are multiple ways to change the configuration using the cli
origin:
Multiple config sections can be change at a time, for instance in the below example vlan 304 is created and +the description of Ethernet1 is changed:
+ +Output:
++ +
{
+ "timestamp": 1628103804792021864,
+ "time": "2021-08-04T20:03:24.792021864+01:00",
+ "results": [
+ {
+ "operation": "UPDATE",
+ "path": "cli:"
+ },
+ {
+ "operation": "UPDATE",
+ "path": "cli:"
+ },
+ {
+ "operation": "UPDATE",
+ "path": "cli:"
+ },
+ {
+ "operation": "UPDATE",
+ "path": "cli:"
+ }
+ ]
+}
+
{
+ "updates": [
+ {
+ "path": "cli:",
+ "value": "interface Ethernet 1",
+ "encoding": "ascii"
+ },
+ {
+ "path": "cli:",
+ "value": "description arista-openmgmt",
+ "encoding": "ascii"
+ },
+ {
+ "path": "cli:",
+ "value": "vlan 304",
+ "encoding": "ascii"
+ },
+ {
+ "path": "cli:",
+ "value": "name test",
+ "encoding": "ascii"
+ }
+ ]
+}
+
Changing the maximum-routes for a BGP neighbor:
+ +Output:
++ +
+ + +updates:
+ - path: "cli:"
+ value: router bgp 65101
+ encoding: ascii
+ - path: "cli:"
+ value: neighbor IPv4-UNDERLAY-PEERS maximum-routes 15500
+ encoding: ascii
+
gnmic -a 192.0.2.214:6030 -u cvpadmin -p arista --insecure --gzip \
+ --encoding ASCII set \
+ --update-path "cli:" \
+ --update-value "router bgp 65101" \
+ --update-path "cli:" \
+ --update-value "neighbor IPv4-UNDERLAY-PEERS maximum-routes 13500"
+
Output:
++ +
+ + +To run show commands that are not converted to JSON and require format="text"
the ASCII
encoding
+can be used from EOS 4.29.2F or newer.
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure get --gzip --encoding ASCII --path "cli:/show platform fap interrupts"
+
Output:
++ +
[
+ {
+ "source": "10.81.117.21:6030",
+ "timestamp": 1698270415643755294,
+ "time": "2023-10-25T22:46:55.643755294+01:00",
+ "updates": [
+ {
+ "Path": "cli:show platform fap interrupts",
+ "values": {
+ "show platform fap interrupts": " Jericho0\n -------------------------------------------------------------------------------------------------------------- \n
+ | Interrupt Bit | Count | First Occurrence | Last Occurrence |\n -------------------------------------------------------------------------------------------------------------- \n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_12[0] | 55 | 2023-10-05 00:02:22 | 2023-10-20 10:29:21 |\n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_13[0] | 39 | 2023-10-05 00:02:21 | 2023-10-16 19:00:15 |\n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_14[0] | 39 | 2023-10-05 00:02:23 | 2023-10-16 19:00:15 |\n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_15[0] | 39 | 2023-10-05 00:02:22 | 2023-10-16 19:00:15 |\n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_20[0] | 67 | 2023-10-05 00:02:26 | 2023-10-24 00:44:24 |\n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_21[0] | 56 | 2023-10-05 00:02:25 | 2023-10-24 00:44:24 |\n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_22[0] | 53 | 2023-10-05 00:02:25 | 2023-10-24 00:45:15 |\n
+ | NBIH_LINK_STATUS_CHANGE_LinkStatusChangeInterruptRegister_23[0] | 55 | 2023-10-05 00:02:24 | 2023-10-24 00:45:15 |\n
+ | IPS_QueueEnteredDel[1] | 6 | 2023-10-11 14:00:20 | 2023-10-11 14:12:02 |\n
+ | EPNI_PP_NewDaErr[0] | 255279 | 2023-10-05 15:06:43 | 2023-10-25 21:46:52 |\n
+ | EPNI_PP_VsiMembershipDeny[1] | 2 | 2023-10-11 02:27:16 | 2023-10-11 14:11:46 |\n
+ | EPNI_PP_EesLastActionNotAc[0] | 255279 | 2023-10-05 15:06:43 | 2023-10-25 21:46:52 |\n
+ | EPNI_PP_EesLastActionNotAc[1] | 47299 | 2023-10-05 13:33:12 | 2023-10-23 16:16:04 |\n
+ | FMAC_FMAC_2_RxLostOfSync_0[32] | 883687 | 2023-10-05 00:02:34 | 2023-10-25 21:46:54 |\n
+ | FMAC_FMAC_2_RxLostOfSync_1[33]
+ <ommitted>
+ \n"
+ }
+ }
+ ]
+ }
+]
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure get \
+ --path ".../state/..." >> outputs/states.json
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure get \
+ --path ".../config/..." >> outputs/configs.json
+
gnmic -a 192.0.2.1:6030 -u admin -p admin --insecure get --path \
+ /network-instances/network-instance >> outputs/network-instances.json
+
gNMI gateway is an opensource project created by +Netflix. Conceptually, gNMI gateway sits as a proxy for multiple gNMI targets. A gNMI client speaks to a common gNMI +service endpoint within the network (gNMI gateway) and specifies a gNMI target with an accompanying path. The gNMI +gateway will in turn initiate the connection to the target device and stream the contents to the originating proxy.
+ +This demo will start the gNMI gateway binary and use gNMIC to stream to a target which is managed by the gNMI gateway.
+Please make adjustments to the targets.json
file to match your environment.
The demo is dependent on the following files:
++ +
{
+ "request": {
+ "default": {
+ "subscribe": {
+ "prefix": {
+ },
+ "subscription": [
+ {
+ "path": {
+ "elem": [
+ {
+ "name": "interfaces"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ },
+ "target": {
+ "DC2-SP02": {
+ "addresses": [
+ "198.51.100.22:6030"
+ ],
+ "credentials": {
+ "username": "ansible",
+ "password": "ansible"
+ },
+ "request": "default",
+ "meta": {
+ "NoTLS": "yes"
+ }
+ },
+ "DC2-LEAF1A": {
+ "addresses": [
+ "198.51.100.5:6030"
+ ],
+ "credentials": {
+ "username": "ansible",
+ "password": "ansible"
+ },
+ "request": "default",
+ "meta": {
+ "NoTLS": "yes"
+ }
+ },
+ "DC2-LF70": {
+ "addresses": [
+ "198.51.100.70:6030"
+ ],
+ "credentials": {
+ "username": "ansible",
+ "password": "ansible"
+ },
+ "request": "default",
+ "meta": {
+ "NoTLS": "yes"
+ }
+ }
+ }
+}
+
gNMI will need to be enabled on the target which is managed by gNMI gateway and a certificate will need to be installed +to use TLS-based authentication. Additional details regarding enabling gnmi on EOS devices can be found +here. Additional details regarding certificate management and configuration can +be found here.
+Note, the server.crt
must be signed by a CA that the switch can resolve.
gnmi-gateway -EnableGNMIServer -ServerTLSCert=server.crt \
+ -ServerTLSKey=server.key -TargetLoaders=json -TargetJSONFile=targets.json
+
Output:
++ +
{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Starting GNMI Gateway."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Clustering is NOT enabled. No locking or cluster coordination will happen."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Starting connection manager."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Starting gNMI server on 0.0.0.0:9339."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Connection manager received a target control message: 3 inserts 0 removes"}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Initializing target DC2-SP02 ([198.51.100.22:6030]) map[NoTLS:yes]."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Initializing target DC2-LEAF1A ([198.51.100.5:6030]) map[NoTLS:yes]."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Target DC2-SP02: Connecting"}
+{"level":"warn","time":"2021-03-19T08:47:35-04:00","message":"DEPRECATED: The 'NoTLS' target flag has been deprecated and will be removed in a future release. Please use 'NoTLSVerify' instead."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Target DC2-SP02: Subscribing"}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Initializing target DC2-LF70 ([198.51.100.70:6030]) map[NoTLS:yes]."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Target DC2-LEAF1A: Connecting"}
+{"level":"warn","time":"2021-03-19T08:47:35-04:00","message":"DEPRECATED: The 'NoTLS' target flag has been deprecated and will be removed in a future release. Please use 'NoTLSVerify' instead."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Target DC2-LEAF1A: Subscribing"}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Target DC2-LF70: Connecting"}
+{"level":"warn","time":"2021-03-19T08:47:35-04:00","message":"DEPRECATED: The 'NoTLS' target flag has been deprecated and will be removed in a future release. Please use 'NoTLSVerify' instead."}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Target DC2-LF70: Subscribing"}
+{"level":"info","time":"2021-03-19T08:47:35-04:00","message":"Target DC2-SP02: Connected"}
+{"level":"info","time":"2021-03-19T08:47:36-04:00","message":"Target DC2-LF70: Connected"}
+{"level":"info","time":"2021-03-19T08:47:36-04:00","message":"Target DC2-LEAF1A: Connected"}
+{"level":"info","time":"2021-03-19T08:47:37-04:00","message":"Target DC2-LF70: Synced"}
+{"level":"info","time":"2021-03-19T08:47:37-04:00","message":"Target DC2-SP02: Synced"}
+{"level":"info","time":"2021-03-19T08:47:38-04:00","message":"Target DC2-LEAF1A: Synced"}
+
The output indicates that gNMI-gateway has started and will now serve gNMI requests to the /interfaces/interface
path
+on behalf of any external gNMI client.
gnmic subscribe -a 192.0.2.1 -u ansible -p ansible --port=9339 \
+ --skip-verify --target=DC2-SP02 --path=/interfaces
+
Output:
+{
+ "source": "192.0.2.1:9339",
+ "subscription-name": "default-1616158143",
+ "timestamp": 1605208845740882713,
+ "time": "2020-11-12T14:20:45.740882713-05:00",
+ "target": "DC2-SP02",
+ "updates": [
+ {
+ "Path": "interfaces/interface[name=Ethernet54/1]/state/tpid",
+ "values": {
+ "interfaces/interface/state/tpid": "openconfig-vlan-types:TPID_0X8100"
+ }
+ }
+ ]
+}
+
Since the gNMI gateway is running locally a query can be issued to the service on port 9339 passing in the target value
+of DC2-SP02
and telemetry will start to stream data back to the client.
gNOIc is a gNOI CLI client:
+ +The following examples shows various gNOIc commands with Arista EOS devices.
+To install run:
+ +To get the version run:
+ +Output:
+version : 0.0.5
+ commit : 26c6248
+ date : 2021-05-12T10:12:55Z
+ gitURL : https://github.com/karimra/gnoic
+ docs : https://gnoic.kmrd.dev
+
interface Management1
+ description oob_management
+ vrf MGMT
+ ip address 192.0.2.118/24
+
+username arista secret 0 arista
+
+management api gnmi
+ transport grpc def
+ vrf MGMT
+
DC1-L2LEAF2A#show management api gnmi
+Enabled: Yes
+Server: running on port 6030, in MGMT VRF
+SSL Profile: none
+QoS DSCP: none
+DC1-L2LEAF2A#
+
Before to use gNOI ping and traceroute, lets run these commands locally:
+$ ssh arista@192.0.2.118
+Password:
+Last login: Thu Jun 3 12:06:25 2021 from 192.0.2.3
+DC1-L2LEAF2A>en
+DC1-L2LEAF2A#bash
+
+Arista Networks EOS shell
+
+[arista@DC1-L2LEAF2A ~]$ ping 172.31.255.0 -c 2
+PING 172.31.255.0 (172.31.255.0) 56(84) bytes of data.
+64 bytes from 172.31.255.0: icmp_seq=1 ttl=63 time=24.6 ms
+64 bytes from 172.31.255.0: icmp_seq=2 ttl=63 time=18.8 ms
+
+--- 172.31.255.0 ping statistics ---
+2 packets transmitted, 2 received, 0% packet loss, time 1001ms
+rtt min/avg/max/mdev = 18.861/21.738/24.616/2.881 ms
+[arista@DC1-L2LEAF2A ~]$
+[arista@DC1-L2LEAF2A ~]$ traceroute -A 172.31.255.0
+traceroute to 172.31.255.0 (172.31.255.0), 30 hops max, 60 byte packets
+ 1 10.90.90.1 (10.90.90.1) [!!] 26.636 ms 29.420 ms 32.113 ms
+ 2 172.31.255.0 (172.31.255.0) [!!] 52.764 ms 53.881 ms 63.213 ms
+[arista@DC1-L2LEAF2A ~]$
+[arista@DC1-L2LEAF2A ~]$ exit
+logout
+DC1-L2LEAF2A#exit
+Connection to 192.0.2.118 closed.
+
gnoic -a 192.0.2.118:6030 -u arista -p arista --insecure system ping \
+ --destination 172.31.255.0 --count 2 --do-not-resolve
+
Output:
+WARN[0000] "192.0.2.118:6030" could not lookup hostname: lookup 118.1.73.10.in-addr.arpa. on 127.0.0.53:53: no such host
+source: "172.31.255.0"
+time: 31200000
+bytes: 64
+sequence: 1
+ttl: 63
+source: "172.31.255.0"
+time: 33900000
+bytes: 64
+sequence: 2
+ttl: 63
+source: "172.31.255.0"
+time: 1001000000
+sent: 2
+received: 2
+min_time: 31251000
+avg_time: 32590000
+max_time: 33930000
+std_dev: 1351000
+
gnoic -a 192.0.2.118:6030 -u arista -p arista --insecure system traceroute \
+ --destination 172.31.255.0 --do-not-resolve
+
Output:
+WARN[0000] "192.0.2.118:6030" could not lookup hostname: lookup 118.1.73.10.in-addr.arpa. on 127.0.0.53:53: no such host
+destination_name: "172.31.255.0"
+destination_address: "172.31.255.0"
+hops: 30
+packet_size: 60
+hop: 1
+address: "10.90.90.1"
+rtt: 21440000
+hop: 1
+address: "10.90.90.1"
+rtt: 23011000
+hop: 1
+address: "10.90.90.1"
+rtt: 31135000
+hop: 2
+address: "172.31.255.0"
+rtt: 62216000
+hop: 2
+address: "172.31.255.0"
+rtt: 63213000
+hop: 2
+address: "172.31.255.0"
+rtt: 71079000
+
Output:
+WARN[0000] "192.0.2.118:6030" could not lookup hostname: lookup 118.1.73.10.in-addr.arpa. on 127.0.0.53:53: no such host
+INFO[0000] "192.0.2.118:6030" key-type=KT_RSA, cert-type=CT_X509, key-size=2048: can_generate: true
++------------------+------------------+
+| Target Name | Can Generate CSR |
++------------------+------------------+
+| 192.0.2.118:6030 | true |
++------------------+------------------+
+
EOS supports gNOI OS Install/Activate/Verification (4.24.2F+) and gNOI System Reboot/Reboot/RebootStatus (4.27.0F+) +that can be used to upload the EOS image, activate that image (set the boot-config) so that it boots with it next time, +verify the image activation was successful and lastly to reboot the device to perform the upgrade.
+To upload an EOS SWI image to a switch we can use the gnoi.os.OS/Installation
RPC:
gnoic -a 192.0.2.1:6030 --insecure --gzip -u admin -p admin \
+ os install \
+ --version 4.29.1F \
+ --pkg EOS.swi
+
Output:
+INFO[0000] starting install RPC
+INFO[0000] target "192.0.2.1:6030": starting Install stream
+INFO[0003] target "192.0.2.1:6030": TransferProgress bytes_received:5242880
+INFO[0003] target "192.0.2.1:6030": TransferProgress bytes_received:10485760
+...
+INFO[0411] target "192.0.2.1:6030": TransferProgress bytes_received:1030750208
+INFO[0413] target "192.0.2.1:6030": sending TransferEnd
+INFO[0413] target "192.0.2.1:6030": TransferProgress bytes_received:1035993088
+INFO[0413] target "192.0.2.1:6030": TransferContent done...
+
To activate the new EOS image (equivalent to running boot system flash:EOS.swi
on the CLI) we can use the
+/gnoi.os.OS/Activation
RPC:
gnoic -a 192.0.2.1:6030 --insecure --gzip -u admin -p admin \
+ os activate \
+ --version 4.29.1F \
+ --no-reboot
+
Output:
+ +Output:
++-------------------+---------+---------------------+
+| Target Name | Version | Activation Fail Msg |
++-------------------+---------+---------------------+
+| 192.0.2.1:6030 | 4.29.1F | |
++-------------------+---------+---------------------+
+
To reboot the device we can use gnoi.system.System/Reboot
RPC and the COLD
method:
++Note on older EOS versions you may get the following error message:
+
ERRO[0009] "192.0.2.1:6030" System Reboot failed: rpc error: code = Unavailable desc = error reading from server: EOF
+Error: there was 1 error(s)
+
These are a few examples leveraging golang and gNOI using the gNOI protobuf specifically the System +service
+The following examples show how to leverage the ping +rpc and traceroute +rpc
+All code can be found within the src directory under +gnoi
+We will be leveraging the gNOI godocs which module can be imported as +github.com/openconfig/gnoi
+Each one of the examples has the following default flags which can be changed based on the environment.
+ +The directory should include the go.mod/go.sum for the correct packages so nothing needs installed on the system at the +current time.
+ ++ +
package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "time"
+
+ log "github.com/golang/glog"
+ system "github.com/openconfig/gnoi/system"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/metadata"
+)
+
+func checkflags(flag ...string) {
+ for _, f := range flag {
+ if f == "" {
+ fmt.Printf("You have an empty flag please fix.")
+ os.Exit(1)
+ }
+ }
+}
+
+func main() {
+ // Add input parameters
+ username := flag.String("username", "admin", "username for connection to gNOI")
+ password := flag.String("password", "admin", "password for connection to gNOI")
+ target := flag.String("target", "", "Target ip or hostname of the device running gNOI")
+ destination := flag.String("destination", "", "Destination of the address to ping to")
+ flag.Parse()
+ // Check for empty flags.
+ checkflags(*username, *password, *target, *destination)
+
+ conn, err := grpc.Dial(*target, grpc.WithInsecure())
+ if err != nil {
+ log.Exitf("Failed to %s Error: %v", target, err)
+ }
+ defer conn.Close()
+
+ // Create the new grpc service connection
+ Sys := system.NewSystemClient(conn)
+ // pass in context blank information with the timeout.
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ // cancel when the function is over.
+ defer cancel()
+ // Since Metadata needs a map to pass into the header of gRPC request create a map for it.
+ metamap := make(map[string]string)
+ // Set the username and password
+ metamap["username"] = *username
+ metamap["password"] = *password
+ // Set the metadata needed in the metadata package
+ md := metadata.New(metamap)
+ // set the ctx to use the metadata in every update.
+ ctx = metadata.NewOutgoingContext(ctx, md)
+ // Try to ping 10 times with a loop
+ for i := 0; i < 10; i++ {
+ response, err := Sys.Ping(ctx, &system.PingRequest{Destination: *destination})
+ if err != nil {
+ log.Fatalf("Error trying to ping: %v", err)
+ }
+ fmt.Println(response.Recv())
+ }
+}
+
Output
+go run ping/ping.go -username admin -password admin -target 172.20.20.2:6030 -destination 2.2.2.2
+source:"2.2.2.2" time:38000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:44000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:37000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:41000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:40000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:38000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:40000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:36000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:44000 bytes:64 sequence:1 ttl:64 <nil>
+source:"2.2.2.2" time:66000 bytes:64 sequence:1 ttl:64 <nil>
+
+ +
package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "time"
+
+ log "github.com/golang/glog"
+ system "github.com/openconfig/gnoi/system"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/metadata"
+)
+
+func checkflags(flag ...string) {
+ for _, f := range flag {
+ if f == "" {
+ fmt.Printf("You have an empty flag please fix.")
+ os.Exit(1)
+ }
+ }
+}
+
+func main() {
+ // Add input parameters
+ username := flag.String("username", "", "username for connection to gNOI")
+ password := flag.String("password", "", "password for connection to gNOI")
+ target := flag.String("target", "", "Target ip or hostname of the device running gNOI")
+ destination := flag.String("destination", "", "Destination of the address to traceroute to")
+ flag.Parse()
+ conn, err := grpc.Dial(*target, grpc.WithInsecure())
+ if err != nil {
+ log.Exitf("Failed to %s Error: %v", target, err)
+ }
+ defer conn.Close()
+ // Check for empty flags.
+ checkflags(*username, *password, *target, *destination)
+ // Create the new grpc service connection
+ Sys := system.NewSystemClient(conn)
+ // pass in context blank information with the timeout.
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ // cancel when the function is over.
+ defer cancel()
+ // Since Metadata needs a map to pass into the header of gRPC request create a map for it.
+ metamap := make(map[string]string)
+ // Set the username and password
+ metamap["username"] = *username
+ metamap["password"] = *password
+ // Set the metadata needed in the metadata package
+ md := metadata.New(metamap)
+ // set the ctx to use the metadata in every update.
+ ctx = metadata.NewOutgoingContext(ctx, md)
+
+ response, err := Sys.Traceroute(ctx, &system.TracerouteRequest{Destination: *destination})
+ if err != nil {
+ log.Fatalf("Cannot trace path: %v", err)
+ }
+ fmt.Println(response.Recv())
+}
+
Output
+ + + + + + + + + +gRPCurl is a command-line tool that lets you interact with gRPC servers:
+ +The following examples shows various gRPCurl commands to interact with Arista EOS devices.
+mkdir -p $GOPATH/src/github.com/openconfig
+git clone https://github.com/openconfig/gnoi.git $GOPATH/src/github.com/openconfig/gnoi
+
interface Management1
+ description oob_management
+ vrf MGMT
+ ip address 192.0.2.118/24
+
+username arista secret 0 arista
+
+management api gnmi
+ transport grpc def
+ vrf MGMT
+
DC1-L2LEAF2A#show management api gnmi
+Enabled: Yes
+Server: running on port 6030, in MGMT VRF
+SSL Profile: none
+QoS DSCP: none
+DC1-L2LEAF2A#
+
Before to use gNOI ping and traceroute, let's run these commands locally:
+$ ssh arista@192.0.2.118
+Password:
+Last login: Thu Jun 3 12:06:25 2021 from 192.0.2.3
+DC1-L2LEAF2A>en
+DC1-L2LEAF2A#bash
+
+Arista Networks EOS shell
+
+[arista@DC1-L2LEAF2A ~]$ ping 172.31.255.0 -c 2
+PING 172.31.255.0 (172.31.255.0) 56(84) bytes of data.
+64 bytes from 172.31.255.0: icmp_seq=1 ttl=63 time=24.6 ms
+64 bytes from 172.31.255.0: icmp_seq=2 ttl=63 time=18.8 ms
+
+--- 172.31.255.0 ping statistics ---
+2 packets transmitted, 2 received, 0% packet loss, time 1001ms
+rtt min/avg/max/mdev = 18.861/21.738/24.616/2.881 ms
+[arista@DC1-L2LEAF2A ~]$
+[arista@DC1-L2LEAF2A ~]$ traceroute -A 172.31.255.0
+traceroute to 172.31.255.0 (172.31.255.0), 30 hops max, 60 byte packets
+ 1 10.90.90.1 (10.90.90.1) [!!] 26.636 ms 29.420 ms 32.113 ms
+ 2 172.31.255.0 (172.31.255.0) [!!] 52.764 ms 53.881 ms 63.213 ms
+[arista@DC1-L2LEAF2A ~]$
+[arista@DC1-L2LEAF2A ~]$ exit
+logout
+DC1-L2LEAF2A#exit
+Connection to 192.0.2.118 closed.
+
grpcurl --plaintext --import-path ${GOPATH}/src --proto github.com/openconfig/gnoi/system/system.proto \
+ describe gnoi.system.System.CancelReboot
+
Output:
+gnoi.system.System.CancelReboot is a method:
+// CancelReboot cancels any pending reboot request.
+rpc CancelReboot ( .gnoi.system.CancelRebootRequest ) returns ( .gnoi.system.CancelRebootResponse );
+
$ grpcurl --plaintext --import-path ${GOPATH}/src --proto github.com/openconfig/gnoi/system/system.proto \
+ describe gnoi.system.System
+
Output:
+gnoi.system.System is a service:
+// The gNOI service is a collection of operational RPC's that allow for the
+// management of a target outside of the configuration and telemetry pipeline.
+service System {
+ // CancelReboot cancels any pending reboot request.
+ rpc CancelReboot ( .gnoi.system.CancelRebootRequest ) returns ( .gnoi.system.CancelRebootResponse );
+ // Ping executes the ping command on the target and streams back
+ // the results. Some targets may not stream any results until all
+ // results are in. If a packet count is not explicitly provided,
+ // 5 is used.
+ rpc Ping ( .gnoi.system.PingRequest ) returns ( stream .gnoi.system.PingResponse );
+ // Reboot causes the target to reboot, possibly at some point in the future.
+ // If the method of reboot is not supported then the Reboot RPC will fail.
+ // If the reboot is immediate the command will block until the subcomponents
+ // have restarted.
+ // If a reboot on the active control processor is pending the service must
+ // reject all other reboot requests.
+ // If a reboot request for active control processor is initiated with other
+ // pending reboot requests it must be rejected.
+ rpc Reboot ( .gnoi.system.RebootRequest ) returns ( .gnoi.system.RebootResponse );
+ // RebootStatus returns the status of reboot for the target.
+ rpc RebootStatus ( .gnoi.system.RebootStatusRequest ) returns ( .gnoi.system.RebootStatusResponse );
+ // SetPackage places a software package (possibly including bootable images)
+ // on the target. The file is sent in sequential messages, each message
+ // up to 64KB of data. A final message must be sent that includes the hash
+ // of the data sent. An error is returned if the location does not exist or
+ // there is an error writing the data. If no checksum is received, the target
+ // must assume the operation is incomplete and remove the partially
+ // transmitted file. The target should initially write the file to a temporary
+ // location so a failure does not destroy the original file.
+ rpc SetPackage ( stream .gnoi.system.SetPackageRequest ) returns ( .gnoi.system.SetPackageResponse );
+ // SwitchControlProcessor will switch from the current route processor to the
+ // provided route processor. If the current route processor is the same as the
+ // one provided it is a NOOP. If the target does not exist an error is
+ // returned.
+ rpc SwitchControlProcessor ( .gnoi.system.SwitchControlProcessorRequest ) returns ( .gnoi.system.SwitchControlProcessorResponse );
+ // Time returns the current time on the target. Time is typically used to
+ // test if a target is actually responding.
+ rpc Time ( .gnoi.system.TimeRequest ) returns ( .gnoi.system.TimeResponse );
+ // Traceroute executes the traceroute command on the target and streams back
+ // the results. Some targets may not stream any results until all
+ // results are in. If a hop count is not explicitly provided,
+ // 30 is used.
+ rpc Traceroute ( .gnoi.system.TracerouteRequest ) returns ( stream .gnoi.system.TracerouteResponse );
+}
+
Example 1)
+grpcurl --plaintext --import-path ${GOPATH}/src \
+ --proto github.com/openconfig/gnoi/system/system.proto list
+
Output:
+ +Example 2)
+grpcurl --plaintext --import-path ${GOPATH}/src \
+ --proto github.com/openconfig/gnoi/system/system.proto \
+ list gnoi.system.System
+
Output:
+gnoi.system.System.CancelReboot
+gnoi.system.System.Ping
+gnoi.system.System.Reboot
+gnoi.system.System.RebootStatus
+gnoi.system.System.SetPackage
+gnoi.system.System.SwitchControlProcessor
+gnoi.system.System.Time
+gnoi.system.System.Traceroute
+
Example 3)
+grpcurl --plaintext --import-path ${GOPATH}/src \
+ --proto github.com/openconfig/gnoi/os/os.proto list gnoi.os.OS
+
Output:
+ +$ grpcurl --plaintext 192.0.2.105:6030 list
+gnmi.gNMI
+gnoi.certificate.CertificateManagement
+gnoi.system.System
+grpc.reflection.v1alpha.ServerReflection
+
grpcurl -H 'username: arista' -H 'password: arista' \
+ -d '{"destination": "172.31.255.0", "count": 2, "do_not_resolve":true}' \
+ -import-path ${GOPATH}/src -proto github.com/openconfig/gnoi/system/system.proto \
+ -plaintext 192.0.2.118:6030 gnoi.system.System/Ping
+
Output:
+{
+ "source": "172.31.255.0",
+ "time": "29800000",
+ "bytes": 64,
+ "sequence": 1,
+ "ttl": 63
+}
+{
+ "source": "172.31.255.0",
+ "time": "25200000",
+ "bytes": 64,
+ "sequence": 2,
+ "ttl": 63
+}
+{
+ "source": "172.31.255.0",
+ "time": "1001000000",
+ "sent": 2,
+ "received": 2,
+ "minTime": "25210000",
+ "avgTime": "27510000",
+ "maxTime": "29810000",
+ "stdDev": "2300000"
+}
+
grpcurl -H 'username: arista' -H 'password: arista' \
+ -d '{"destination": "172.31.255.0", "max_ttl": 50, "do_not_resolve":true}' \
+ -import-path ${GOPATH}/src -proto github.com/openconfig/gnoi/system/system.proto \
+ -plaintext 192.0.2.118:6030 gnoi.system.System/Traceroute
+
Output:
+{
+ "destinationName": "172.31.255.0",
+ "destinationAddress": "172.31.255.0",
+ "hops": 50,
+ "packetSize": 60
+}
+{
+ "hop": 1,
+ "address": "10.90.90.1",
+ "rtt": "16589000"
+}
+{
+ "hop": 1,
+ "address": "10.90.90.1",
+ "rtt": "17886000"
+}
+{
+ "hop": 1,
+ "address": "10.90.90.1",
+ "rtt": "23219000"
+}
+{
+ "hop": 2,
+ "address": "172.31.255.0",
+ "rtt": "46537000"
+}
+{
+ "hop": 2,
+ "address": "172.31.255.0",
+ "rtt": "47873000"
+}
+{
+ "hop": 2,
+ "address": "172.31.255.0",
+ "rtt": "55376000"
+}
+
gRPC - Google Remote Procedure Call
+gRPC uses protobuf and HTTP/2
+gNOI - gRPC Network Operations Interface
+gNOI defines a set of gRPC-based microservices for executing operational commands on network devices.
+gNOI github repository
+As example, this gNOI proto file defines the
+service System
with the RPC Traceroute
and Ping
Please refer to this link for the gNOI support by EOS.
+Examples:
+ + + + + + + + + +The following example uses the goarista go module for gNMI to +interact with a device. Within this very simplistic getting started example main.go will simply perform a get method to +the device for all paths.
+package main
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/aristanetworks/glog"
+ "github.com/aristanetworks/goarista/gnmi"
+ pb "github.com/openconfig/gnmi/proto/gnmi"
+)
+
+var cfg = &gnmi.Config{
+ Addr: "10.20.30.67:6030",
+ Username: "ansible",
+ Password: "ansible",
+}
+
+func main() {
+ paths := []string{"/"}
+ var origin = "openconfig"
+ //var origin = "eos_native"
+ ctx := gnmi.NewContext(context.Background(), cfg)
+ client, err := gnmi.Dial(cfg)
+ if err != nil {
+ glog.Fatal(err)
+ }
+
+ req, err := gnmi.NewGetRequest(gnmi.SplitPaths(paths), origin)
+ if err != nil {
+ glog.Fatal(err)
+ }
+ if cfg.Addr != "" {
+ if req.Prefix == nil {
+ req.Prefix = &pb.Path{}
+ }
+ req.Prefix.Target = cfg.Addr
+ }
+
+ err = gnmi.GetWithRequest(ctx, client, req)
+ if err != nil {
+ glog.Fatal(err)
+ }
+ fmt.Println(err)
+}
+
Copy the above code into a file and run via the following command.
+ +{
+ "openconfig-acl:acl": {
+ "state": {
+ "counter-capability": "AGGREGATE_ONLY"
+ }
+ },
+ "arista-exp-eos:arista": {
+ "eos": {
+ "arista-exp-eos-igmpsnooping:bridging": {
+ "igmpsnooping": {
+ "config": {}
+ }
+ },
+ "arista-exp-eos-mlag:mlag": {
+ "config": {
+ "dual-primary-action": "action-none",
+
In the examples folder we provide a variety of examples that will show how to use some of the many third party +tools to interact with one of the GRPC +interfaces(gNMI,gNOI and gRIBI) within Arista EOS.
+switch1#show running-config section netconf
+management api netconf
+ transport ssh test
+ vrf MGMT
+
>>> from ncclient import manager
+>>> eos=manager.connect(host="198.51.100.221", port="830", timeout=30, username="arista", password="arista", hostkey_verify=False)
+>>>
+>>> eos.connected
+True
+>>> eos.timeout
+30
+>>> eos.session_id
+'1292406600'
+>>>
+>>> assert("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring" in eos.server_capabilities), "NetConf server not compliant with https://tools.ietf.org/html/rfc6022"
+>>>
+>>> conf = '''
+... <config>
+... <system xmlns="http://openconfig.net/yang/system">
+... <config>
+... <domain-name>abc.xyz</domain-name>
+... </config>
+... </system>
+... </config>
+... '''
+>>>
+>>> eos.edit_config(target = "running", config = conf, default_operation="merge")
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:33ca18d3-43b5-4277-a6ce-9a751f74cada"><ok></ok></rpc-reply>
+>>>
+>>> domain_name='''
+... <system xmlns="http://openconfig.net/yang/system">
+... <config>
+... <domain-name>
+... </domain-name>
+... </config>
+... </system>
+... '''
+>>>
+>>> domain_name_conf = eos.get_config(source="running", filter=("subtree", domain_name))
+>>> print (domain_name_conf)
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:a43cfae5-3215-4f99-97ce-ff61ca1e285c"><data time-modified="2021-07-11T12:29:49.133333939Z"><system xmlns="http://openconfig.net/yang/system"><config><domain-name>abc.xyz</domain-name></config></system></data></rpc-reply>
+>>>
+>>> eos.close_session()
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:1841896a-9c97-467d-aef8-9a405b51d298"><ok></ok></rpc-reply>
+>>>
+>>> eos.connected
+False
+>>>
+>>> exit()
+
>>> from lxml import etree
+>>>
+>>> system_e = etree.Element("system")
+>>> dns_e = etree.SubElement(system_e, "dns")
+>>> servers_e = etree.SubElement(dns_e, "servers")
+>>> server_e = etree.SubElement(servers_e, "server")
+>>> address_e = etree.SubElement(server_e, "address")
+>>> config_e = etree.SubElement(server_e, "config")
+>>> address_e.text = "8.8.8.8"
+>>>
+>>> address_e.text
+'8.8.8.8'
+>>>
+>>> etree.tostring(system_e)
+b'<system><dns><servers><server><address>8.8.8.8</address><config/></server></servers></dns></system>'
+>>>
+>>> etree.tostring(system_e, pretty_print = True)
+b'<system>\n <dns>\n <servers>\n <server>\n <address>8.8.8.8</address>\n <config/>\n </server>\n </servers>\n </dns>\n</system>\n'
+>>>
+>>> etree.dump(system_e)
+<system>
+ <dns>
+ <servers>
+ <server>
+ <address>8.8.8.8</address>
+ <config/>
+ </server>
+ </servers>
+ </dns>
+</system>
+>>>
+>>> from ncclient import manager
+>>> eos=manager.connect(host="198.51.100.221", port="830", timeout=30, username="arista", password="arista", hostkey_verify=False)
+>>> eos.connected
+True
+>>>
+>>> print(eos.get_config(source="running", filter=("subtree", system_e)))
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:ab16e734-04df-4d4f-8efe-27963ece586c"><data time-modified="2021-07-11T12:29:49.138275819Z"><system xmlns="http://openconfig.net/yang/system"><dns><servers><server><address>8.8.8.8</address><config><address>8.8.8.8</address></config></server></servers></dns></system></data></rpc-reply>
+>>>
+>>> eos.close_session()
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:2eed88ee-106b-44d1-b196-f79611512b25"><ok></ok></rpc-reply>
+>>>
+>>> exit()
+
There are many python scripts using ncclient in this directory.
+To execute one of these scripts, run as example this command:
+ +get
operation to
+ retrieve the configuration and state data. It uses a filter to specify the portion of the configuration and state data
+ to retrieve.get-config
+ operation with a filter to retrieve part of the configuration.edit-config
operation with the merge
operation (which is the default operation for edit-config
)edit-config
operation with the replace
operationedit-config
operation with the delete
operationedit-config
operation and EOS data modeledit-config
operation with the candidate
configuration datastore. It uses a lock
operation and commit
+ operation.candidate_configuration_discard_changes.py.
+ uses the edit-config
operation with the candidate
configuration datastore. It uses a lock
operation and
+ discard_change
operation to revert the candidate configuration to the current running configuration (insteaf of
+ commiting the candidate configuration). #### XML output parsing
parse_xml_output.py uses the
+ get
operation to retrieve data from the device and then parse this data.
switch1#show running-config section netconf
+management api netconf
+ transport ssh test
+ vrf MGMT
+
In order to open a NETCONF session inside an SSH connection, there are two options:
+ssh username@device -s netconf
netconf start-client
Once the NETCONF session is open, the NETCONF server (EOS device) advertises its capabilities.
+You must advertise the client capabilities. Example:
+<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <capabilities>
+ <capability>urn:ietf:params:netconf:base:1.0</capability>
+ <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
+ <capability>urn:ietf:params:netconf:capability:confimed-commit:1.0</capability>
+ <capability>urn:ietf:params:netconf:capability:writable-running:1.0</capability>
+ <capability>urn:ietf:params:netconf:capability:validate:1.0</capability>
+ </capabilities>
+</hello>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
+ <get>
+ </get>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2">
+ <get>
+ <filter type="subtree">
+ <interfaces>
+ <interface>
+ <name>Ethernet3</name>
+ <state>
+ <oper-status>
+ </oper-status>
+ </state>
+ </interface>
+ </interfaces>
+ </filter>
+ </get>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="3">
+ <get-config>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="4">
+ <get-config>
+ <source>
+ <running/>
+ </source>
+ <filter>
+ <interfaces>
+ <interface>
+ <name>Ethernet3</name>
+ </interface>
+ </interfaces>
+ </filter>
+ </get-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="5">
+ <get-config>
+ <source>
+ <running/>
+ </source>
+ <filter>
+ <interfaces>
+ <interface>
+ <name>Ethernet3</name>
+ <config>
+ <description>
+ </description>
+ </config>
+ </interface>
+ </interfaces>
+ </filter>
+ </get-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="6">
+ <lock>
+ <target>
+ <running/>
+ </target>
+ </lock>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="7">
+<edit-config>
+ <target>
+ <running/>
+ </target>
+ <default-operation>merge</default-operation>
+ <commands>
+ <command>vlan 198</command>
+ <command>name test198</command>
+ <command>interface ethernet6</command>
+ <command>description test</command>
+ <command>switchport access vlan 98</command>
+ </commands>
+</edit-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="8">
+<edit-config>
+ <target>
+ <running/>
+ </target>
+ <default-operation>merge</default-operation>
+ <config>
+ <interfaces>
+ <interface>
+ <name>Ethernet4</name>
+ <config>
+ <description>This is the best interface</description>
+ </config>
+ </interface>
+ </interfaces>
+ </config>
+ </edit-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="9">
+<edit-config>
+ <target>
+ <running/>
+ </target>
+ <default-operation>none</default-operation>
+ <config>
+ <system xmlns="http://arista.com/yang/openconfig/system/">
+ <dns>
+ <servers>
+ <server>
+ <address operation="delete">1.1.1.1</address>
+ </server>
+ </servers>
+ </dns>
+ </system>
+ </config>
+</edit-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="10">
+ <unlock>
+ <target>
+ <running/>
+ </target>
+ </unlock>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="11">
+ <copy-config>
+ <target>
+ <url>
+ flash:/test.cfg
+ </url>
+ </target>
+ <source>
+ <running/>
+ </source>
+ </copy-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="12">
+ <copy-config>
+ <target>
+ <startup/>
+ </target>
+ <source>
+ <running/>
+ </source>
+ </copy-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="13">
+ <lock>
+ <target>
+ <candidate/>
+ </target>
+ </lock>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="14">
+<edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <default-operation>merge</default-operation>
+ <config>
+ <interfaces>
+ <interface>
+ <name>Ethernet5/1</name>
+ <config>
+ <description>This is the best interface</description>
+ </config>
+ </interface>
+ </interfaces>
+ </config>
+ </edit-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="20">
+ <unlock>
+ <target>
+ <candidate/>
+ </target>
+ </unlock>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="21">
+<edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <default-operation>merge</default-operation>
+ <config>
+ <system>
+ <config>
+ <hostname>test</hostname>
+ </config>
+ </system>
+ </config>
+ </edit-config>
+</rpc>
+]]>]]>
+
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="5">
+ <get-config>
+ <source>
+ <candidate/>
+ </source>
+ <filter>
+ <system>
+ <config>
+ <hostname></hostname>
+ </config>
+ </system>
+ </filter>
+ </get-config>
+</rpc>
+]]>]]>
+
If you decide to not commit the candidate configuration, you can revert the candidate configuration to the current +running configuration
+<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="90">
+ <discard-changes/>
+</rpc>
+]]>]]>
+
pyang is a python program.
+We can use it to:
+We need YANG modules so we can use Pyang.
+cp public/release/models/*.yang yang_modules/.
+cp -R public/release/models/*/*.yang yang_modules/.
+cp public/third_party/ietf/*.yang yang_modules/.
+
It has all the YANG files published on the OpenConfig repository
+ +A YANG module can be translated into an XML syntax called YIN. The translated module is called a YIN module. The YANG +and YIN formats contain equivalent information using different notations: YIN is YANG in XML. A YANG module can be +translated into YIN syntax without losing any information.
+Example (openconfig-bgp.yin is the YIN equivalent of openconfig-bgp.yang)
+ ++ +
module: openconfig-interfaces
+ +--rw interfaces
+ +--rw interface* [name]
+ +--rw name -> ../config/name
+ +--rw config
+ | +--rw name? string
+ | +--rw type identityref
+ | +--rw mtu? uint16
+ | +--rw loopback-mode? boolean
+ | +--rw description? string
+ | +--rw enabled? boolean
+ +--ro state
+ | +--ro name? string
+ | +--ro type identityref
+ | +--ro mtu? uint16
+ | +--ro loopback-mode? boolean
+ | +--ro description? string
+ | +--ro enabled? boolean
+ | +--ro ifindex? uint32
+ | +--ro admin-status enumeration
+ | +--ro oper-status enumeration
+ | +--ro last-change? oc-types:timeticks64
+ | +--ro logical? boolean
+ | +--ro management? boolean
+ | +--ro cpu? boolean
+ | +--ro counters
+ | +--ro in-octets? oc-yang:counter64
+ | +--ro in-pkts? oc-yang:counter64
+ | +--ro in-unicast-pkts? oc-yang:counter64
+ | +--ro in-broadcast-pkts? oc-yang:counter64
+ | +--ro in-multicast-pkts? oc-yang:counter64
+ | +--ro in-discards? oc-yang:counter64
+ | +--ro in-errors? oc-yang:counter64
+ | +--ro in-unknown-protos? oc-yang:counter64
+ | +--ro in-fcs-errors? oc-yang:counter64
+ | +--ro out-octets? oc-yang:counter64
+ | +--ro out-pkts? oc-yang:counter64
+ | +--ro out-unicast-pkts? oc-yang:counter64
+ | +--ro out-broadcast-pkts? oc-yang:counter64
+ | +--ro out-multicast-pkts? oc-yang:counter64
+ | +--ro out-discards? oc-yang:counter64
+ | +--ro out-errors? oc-yang:counter64
+ | +--ro carrier-transitions? oc-yang:counter64
+ | +--ro last-clear? oc-types:timeticks64
+ +--rw hold-time
+ | +--rw config
+ | | +--rw up? uint32
+ | | +--rw down? uint32
+ | +--ro state
+ | +--ro up? uint32
+ | +--ro down? uint32
+ +--rw subinterfaces
+ +--rw subinterface* [index]
+ +--rw index -> ../config/index
+ +--rw config
+ | +--rw index? uint32
+ | +--rw description? string
+ | +--rw enabled? boolean
+ +--ro state
+ +--ro index? uint32
+ +--ro description? string
+ +--ro enabled? boolean
+ +--ro name? string
+ +--ro ifindex? uint32
+ +--ro admin-status enumeration
+ +--ro oper-status enumeration
+ +--ro last-change? oc-types:timeticks64
+ +--ro logical? boolean
+ +--ro management? boolean
+ +--ro cpu? boolean
+ +--ro counters
+ +--ro in-octets? oc-yang:counter64
+ +--ro in-pkts? oc-yang:counter64
+ +--ro in-unicast-pkts? oc-yang:counter64
+ +--ro in-broadcast-pkts? oc-yang:counter64
+ +--ro in-multicast-pkts? oc-yang:counter64
+ +--ro in-discards? oc-yang:counter64
+ +--ro in-errors? oc-yang:counter64
+ +--ro in-unknown-protos? oc-yang:counter64
+ +--ro in-fcs-errors? oc-yang:counter64
+ +--ro out-octets? oc-yang:counter64
+ +--ro out-pkts? oc-yang:counter64
+ +--ro out-unicast-pkts? oc-yang:counter64
+ +--ro out-broadcast-pkts? oc-yang:counter64
+ +--ro out-multicast-pkts? oc-yang:counter64
+ +--ro out-discards? oc-yang:counter64
+ +--ro out-errors? oc-yang:counter64
+ +--ro carrier-transitions? oc-yang:counter64
+ +--ro last-clear? oc-types:timeticks64
+
+ +
module: openconfig-interfaces
+ +--rw interfaces
+ +--rw interface* [name]
+ +--ro state
+ +--ro name? string
+ +--ro type identityref
+ +--ro mtu? uint16
+ +--ro loopback-mode? boolean
+ +--ro description? string
+ +--ro enabled? boolean
+ +--ro ifindex? uint32
+ +--ro admin-status enumeration
+ +--ro oper-status enumeration
+ +--ro last-change? oc-types:timeticks64
+ +--ro logical? boolean
+ +--ro management? boolean
+ +--ro cpu? boolean
+ +--ro counters
+ +--ro in-octets? oc-yang:counter64
+ +--ro in-pkts? oc-yang:counter64
+ +--ro in-unicast-pkts? oc-yang:counter64
+ +--ro in-broadcast-pkts? oc-yang:counter64
+ +--ro in-multicast-pkts? oc-yang:counter64
+ +--ro in-discards? oc-yang:counter64
+ +--ro in-errors? oc-yang:counter64
+ +--ro in-unknown-protos? oc-yang:counter64
+ +--ro in-fcs-errors? oc-yang:counter64
+ +--ro out-octets? oc-yang:counter64
+ +--ro out-pkts? oc-yang:counter64
+ +--ro out-unicast-pkts? oc-yang:counter64
+ +--ro out-broadcast-pkts? oc-yang:counter64
+ +--ro out-multicast-pkts? oc-yang:counter64
+ +--ro out-discards? oc-yang:counter64
+ +--ro out-errors? oc-yang:counter64
+ +--ro carrier-transitions? oc-yang:counter64
+ +--ro last-clear? oc-types:timeticks64
+
+ +
module: openconfig-interfaces
+ +--rw interfaces
+ +--rw interface* [name]
+ +--rw name -> ../config/name
+ +--rw config
+ | +--rw name? string
+ | +--rw type identityref
+ | +--rw mtu? uint16
+ | +--rw loopback-mode? boolean
+ | +--rw description? string
+ | +--rw enabled? boolean
+ +--ro state
+ | +--ro name? string
+ | +--ro type identityref
+ | +--ro mtu? uint16
+ | +--ro loopback-mode? boolean
+ | +--ro description? string
+ | +--ro enabled? boolean
+ | +--ro ifindex? uint32
+ | +--ro admin-status enumeration
+ | +--ro oper-status enumeration
+ | +--ro last-change? oc-types:timeticks64
+ | +--ro logical? boolean
+ | +--ro management? boolean
+ | +--ro cpu? boolean
+ | +--ro counters
+ | ...
+ +--rw hold-time
+ | +--rw config
+ | | ...
+ | +--ro state
+ | ...
+ +--rw subinterfaces
+ +--rw subinterface* [index]
+ ...
+
+ +
module: openconfig-bgp
+ +--rw bgp
+ +--rw neighbors
+ +--rw neighbor* [neighbor-address]
+ +--rw neighbor-address -> ../config/neighbor-address
+ +--rw config
+ | ...
+ +--ro state
+ | ...
+ +--rw timers
+ | ...
+ +--rw transport
+ | ...
+ +--rw error-handling
+ | ...
+ +--rw graceful-restart
+ | ...
+ +--rw logging-options
+ | ...
+ +--rw ebgp-multihop
+ | ...
+ +--rw route-reflector
+ | ...
+ +--rw as-path-options
+ | ...
+ +--rw use-multiple-paths
+ | ...
+ +--rw apply-policy
+ | ...
+ +--rw afi-safis
+ | ...
+ +--rw enable-bfd
+
+ +
module: openconfig-bgp
+ +--rw bgp
+ +--rw neighbors
+ +--rw neighbor* [neighbor-address]
+ +--rw config
+ +--rw peer-group? -> ../../../../peer-groups/peer-group/peer-group-name
+ +--rw neighbor-address? oc-inet:ip-address
+ +--rw enabled? boolean
+ +--rw peer-as? oc-inet:as-number
+ +--rw local-as? oc-inet:as-number
+ +--rw peer-type? oc-bgp-types:peer-type
+ +--rw auth-password? oc-types:routing-password
+ +--rw remove-private-as? oc-bgp-types:remove-private-as-option
+ +--rw route-flap-damping? boolean
+ +--rw send-community? oc-bgp-types:community-type
+ +--rw description? string
+
+ +
module: openconfig-bgp
+ +--rw bgp
+ +--rw neighbors
+ +--rw neighbor* [neighbor-address]
+ +--ro state
+ +--ro peer-group? -> ../../../../peer-groups/peer-group/peer-group-name
+ +--ro neighbor-address? oc-inet:ip-address
+ +--ro enabled? boolean
+ +--ro peer-as? oc-inet:as-number
+ +--ro local-as? oc-inet:as-number
+ +--ro peer-type? oc-bgp-types:peer-type
+ +--ro auth-password? oc-types:routing-password
+ +--ro remove-private-as? oc-bgp-types:remove-private-as-option
+ +--ro route-flap-damping? boolean
+ +--ro send-community? oc-bgp-types:community-type
+ +--ro description? string
+ +--ro session-state? enumeration
+ +--ro last-established? oc-types:timeticks64
+ +--ro established-transitions? oc-yang:counter64
+ +--ro supported-capabilities* identityref
+ +--ro messages
+ | ...
+ +--ro queues
+ | ...
+ +--ro dynamically-configured? boolean
+
pyang openconfig-bgp.yang -f tree --tree-path=/bgp/neighbors/neighbor/afi-safis \
+ --tree-depth=6
+
+ +
module: openconfig-bgp
+ +--rw bgp
+ +--rw neighbors
+ +--rw neighbor* [neighbor-address]
+ +--rw afi-safis
+ +--rw afi-safi* [afi-safi-name]
+ +--rw afi-safi-name -> ../config/afi-safi-name
+ +--rw config
+ | ...
+ +--ro state
+ | ...
+ +--rw graceful-restart
+ | ...
+ +--rw add-paths
+ | ...
+ +--rw apply-policy
+ | ...
+ +--rw ipv4-unicast
+ | ...
+ +--rw ipv6-unicast
+ | ...
+ +--rw ipv4-labeled-unicast
+ | ...
+ +--rw ipv6-labeled-unicast
+ | ...
+ +--rw l3vpn-ipv4-unicast
+ | ...
+ +--rw l3vpn-ipv6-unicast
+ | ...
+ +--rw l3vpn-ipv4-multicast
+ | ...
+ +--rw l3vpn-ipv6-multicast
+ | ...
+ +--rw l2vpn-vpls
+ | ...
+ +--rw l2vpn-evpn
+ | ...
+ +--rw srte-policy-ipv4
+ | ...
+ +--rw srte-policy-ipv6
+ | ...
+ +--rw use-multiple-paths
+
PyangBind is a pyang plugin.
+Please visit this link if you need help about Pyang.
+It generates Python classes from a YANG module.
+It converts YANG module into a Python module. +This Python module can be then used to generate data which conforms with the data model defined in YANG.
+We need YANG modules so we can use Pyang and Pyangbind.
+Run this command to verify
+ +cp public/release/models/*.yang yang_modules/.
+cp -R public/release/models/*/*.yang yang_modules/.
+cp public/third_party/ietf/*.yang yang_modules/.
+
Verify it has all the YANG files published on the OpenConfig repository
+ +pyang --plugindir $HOME/.local/lib/python3.6/site-packages/pyangbind/plugin/ -f pybind -o oc_bgp.py openconfig-bgp.yang
+
The above command generated the python module oc_bgp.py
from the openconfig-bgp.yang
file.
+Run this command to verify:
The file pyangbind_demo.py uses
+the new python module oc_bgp.py
and generates this OpenConfig configuration file demo.json
This OpenConfig configuration file demo.json can be loaded on a switch using the gNMI Set RPC
+Please visit this link if you need help with gNMIc installation
+Please visit this link if you need help to configure EOS for gNMI
+gnmic -a 192.0.2.117:6030 --insecure -u arista -p arista get \
+ --path '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp'
+
gnmic -a 192.0.2.117:6030 --insecure -u arista -p arista set \
+ --replace-path '/network-instances/network-instance[name=default]/protocols/protocol[name=BGP]/bgp' \
+ --replace-file demo.json
+
The following example uses the pygnmi python module to talk to gNMI +devices.
+# Modules
+from pygnmi.client import gNMIclient
+import json
+
+# Variables
+host = ('198.51.100.67', '6030')
+
+# Body
+if __name__ == '__main__':
+ with gNMIclient(target=host, username='ansible', password='ansible', insecure=True) as gc:
+ result = gc.get(path=['openconfig:interfaces'])
+ print(json.dumps(result, indent=4))
+
Assuming that the pygnmi
module has been installed, this can be executed via the following command.
The following will simply run the
+gnmi_example.py
file using python3
+to get the openconfig interfaces.
Truncated output
+{
+ "notification": [
+ {
+ "timestamp": 0,
+ "update": [
+ {
+ "path": "interfaces",
+ "json_ietf_val": {
+ "openconfig-interfaces:interface": [
+ {
+ "config": {
+ "enabled": true,
+ "arista-intf-augments:load-interval": 300,
+ "loopback-mode": false,
+ "mtu": 0,
+ "name": "Ethernet1",
+ "openconfig-vlan:tpid": "openconfig-vlan-types:TPID_0X8100",
+ "type": "iana-if-type:ethernetCsmacd"
+ },
+
The file capabilities.py uses the +pygnmi python module to get the gNMI capabilities.
+ ++ +
{'gnmi_version': '0.7.0',
+ 'supported_encodings': ['json', 'json_ietf', 'ascii'],
+ 'supported_models': [{'name': 'arista-exp-eos-varp-net-inst',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-acl',
+ 'organization': 'OpenConfig working group',
+ 'version': '1.1.1'},
+ {'name': 'arista-system-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-system-management',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.0'},
+ {'name': 'arista-isis-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-rib-bgp-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.5.0'},
+ {'name': 'openconfig-platform-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '1.0.0'},
+ {'name': 'openconfig-network-instance',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.13.2'},
+ {'name': 'arista-bgp-augments',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-exp-eos-igmpsnooping',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'ietf-netconf',
+ 'organization': 'IETF NETCONF (Network Configuration) '
+ 'Working Group',
+ 'version': ''},
+ {'name': 'openconfig-policy-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.1.1'},
+ {'name': 'openconfig-rib-bgp',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.6.0'},
+ {'name': 'arista-local-routing-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-exp-eos-varp-intf',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-interfaces-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-rpc-netconf',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-platform-psu',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.1'},
+ {'name': 'openconfig-packet-match-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '1.0.2'},
+ {'name': 'openconfig-platform-fan',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'openconfig-inet-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.3.3'},
+ {'name': 'openconfig-igmp',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.0'},
+ {'name': 'openconfig-aaa-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.4.1'},
+ {'name': 'openconfig-lldp',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.1'},
+ {'name': 'arista-relay-agent-deviations',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-intf-augments',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-qos-augments',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'ietf-yang-types',
+ 'organization': 'IETF NETMOD (NETCONF Data Modeling '
+ 'Language) Working Group',
+ 'version': ''},
+ {'name': 'openconfig-openflow',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.2'},
+ {'name': 'iana-if-type',
+ 'organization': 'IANA',
+ 'version': ''},
+ {'name': 'arista-exp-eos-vxlan-config',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-routing-policy-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-aaa',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.4.3'},
+ {'name': 'openconfig-if-ip',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.0.0'},
+ {'name': 'arista-srte-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-local-routing-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-lacp-augments',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-bgp-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-exp-eos-multicast',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-interfaces',
+ 'organization': 'OpenConfig working group',
+ 'version': '2.4.3'},
+ {'name': 'openconfig-extensions',
+ 'organization': 'OpenConfig working group',
+ 'version': ''},
+ {'name': 'openconfig-system-terminal',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.3.1'},
+ {'name': 'openconfig-bgp-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '5.0.2'},
+ {'name': 'arista-netinst-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-system-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-segment-routing',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.0.4'},
+ {'name': 'openconfig-platform',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.12.2'},
+ {'name': 'openconfig-pf-srte',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'arista-vlan-deviations',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-bfd',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.0'},
+ {'name': 'openconfig-if-tunnel',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'openconfig-alarms',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.3.2'},
+ {'name': 'openconfig-if-aggregate',
+ 'organization': 'OpenConfig working group',
+ 'version': '2.4.2'},
+ {'name': 'arista-acl-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-acl-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-messages-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-network-instance-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.8.2'},
+ {'name': 'openconfig-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.6.0'},
+ {'name': 'ietf-interfaces',
+ 'organization': 'IETF NETMOD (Network Modeling) Working '
+ 'Group',
+ 'version': ''},
+ {'name': 'openconfig-procmon',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.4.0'},
+ {'name': 'arista-exp-eos-qos',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-exp-eos',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-qos-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-aft',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.4.0'},
+ {'name': 'arista-isis-augments',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-packet-match',
+ 'organization': 'OpenConfig working group',
+ 'version': '1.1.1'},
+ {'name': 'arista-lldp-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-if-ethernet',
+ 'organization': 'OpenConfig working group',
+ 'version': '2.7.2'},
+ {'name': 'openconfig-mpls-sr',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.0.1'},
+ {'name': 'openconfig-policy-forwarding',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.1'},
+ {'name': 'arista-intf-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-isis-lsdb-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.4.2'},
+ {'name': 'vlan-translation',
+ 'organization': 'Arista Networks',
+ 'version': ''},
+ {'name': 'arista-gnoi-cert',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-network-instance-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-bfd-augments',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-vlan-augments',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-hercules-interfaces',
+ 'organization': 'OpenConfig Hercules Working Group',
+ 'version': '0.2.0'},
+ {'name': 'arista-lacp-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-srte-augments',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-igmp-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'openconfig-lacp',
+ 'organization': 'OpenConfig working group',
+ 'version': '1.1.1'},
+ {'name': 'openconfig-routing-policy',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.1.1'},
+ {'name': 'arista-lacp-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-system-logging',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.3.1'},
+ {'name': 'openconfig-aft-types',
+ 'organization': 'OpenConfig Working Group',
+ 'version': '0.3.3'},
+ {'name': 'openconfig-network-instance-l3',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.11.1'},
+ {'name': 'arista-bgp-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-rpol-augments',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-eos-types',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-qos-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.1'},
+ {'name': 'arista-openflow-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-mpls-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.1.0'},
+ {'name': 'openconfig-hercules-qos',
+ 'organization': 'OpenConfig Hercules Working Group',
+ 'version': '0.1.0'},
+ {'name': 'openconfig-bgp',
+ 'organization': 'OpenConfig working group',
+ 'version': '6.0.0'},
+ {'name': 'arista-platform-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-system-augments',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-exp-eos-mlag',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-system',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.8.0'},
+ {'name': 'openconfig-isis',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.4.2'},
+ {'name': 'openconfig-lldp-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'openconfig-vlan',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.2.0'},
+ {'name': 'openconfig-if-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.1'},
+ {'name': 'openconfig-relay-agent',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'arista-lldp-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-aft-augments',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-vlan-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.1.0'},
+ {'name': 'arista-mpls-augments',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'arista-mpls-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'openconfig-alarm-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.1'},
+ {'name': 'openconfig-hercules-platform',
+ 'organization': 'OpenConfig Hercules Working Group',
+ 'version': '0.2.0'},
+ {'name': 'openconfig-ospfv2',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.2'},
+ {'name': 'ietf-netconf-monitoring',
+ 'organization': 'IETF NETCONF (Network Configuration) '
+ 'Working Group',
+ 'version': ''},
+ {'name': 'arista-exp-eos-evpn',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-exp-eos-vxlan',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-platform-port',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.3.2'},
+ {'name': 'openconfig-messages',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.0.1'},
+ {'name': 'openconfig-platform-cpu',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'openconfig-if-poe',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'openconfig-pim',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.0'},
+ {'name': 'openconfig-openflow-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.2'},
+ {'name': 'openconfig-mpls',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.1.0'},
+ {'name': 'openconfig-platform-linecard',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'openconfig-mpls-ldp',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.0.2'},
+ {'name': 'openconfig-bgp-policy',
+ 'organization': 'OpenConfig working group',
+ 'version': '6.0.1'},
+ {'name': 'openconfig-mpls-rsvp',
+ 'organization': 'OpenConfig working group',
+ 'version': '3.0.1'},
+ {'name': 'arista-exp-eos-qos-config',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-yang-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.1'},
+ {'name': 'openconfig-qos',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.2.3'},
+ {'name': 'openconfig-local-routing',
+ 'organization': 'OpenConfig working group',
+ 'version': '1.0.2'},
+ {'name': 'ietf-inet-types',
+ 'organization': 'IETF NETMOD (NETCONF Data Modeling '
+ 'Language) Working Group',
+ 'version': ''},
+ {'name': 'arista-rpol-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-pim-augments',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-pim-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.1'},
+ {'name': 'arista-bfd-notsupported-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-lldp-augments',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''},
+ {'name': 'arista-exp-eos-qos-acl-config',
+ 'organization': 'Arista Networks <http://arista.com/>',
+ 'version': ''},
+ {'name': 'openconfig-isis-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.4.2'},
+ {'name': 'openconfig-ospf-policy',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.3'},
+ {'name': 'openconfig-ospf-types',
+ 'organization': 'OpenConfig working group',
+ 'version': '0.1.3'},
+ {'name': 'arista-bfd-deviations',
+ 'organization': 'Arista Networks, Inc.',
+ 'version': ''}]}
+
The file get.py uses the +pygnmi python module and uses the gNMI GET RPC
+ ++ +
{
+ "notification": [
+ {
+ "timestamp": 0,
+ "update": [
+ {
+ "path": "interfaces/interface[name=Ethernet1]/state/counters",
+ "val": {
+ "openconfig-interfaces:in-broadcast-pkts": "2",
+ "openconfig-interfaces:in-discards": "0",
+ "openconfig-interfaces:in-errors": "0",
+ "openconfig-interfaces:in-fcs-errors": "0",
+ "openconfig-interfaces:in-multicast-pkts": "189439",
+ "openconfig-interfaces:in-octets": "48284395",
+ "openconfig-interfaces:in-unicast-pkts": "416884",
+ "openconfig-interfaces:out-broadcast-pkts": "14",
+ "openconfig-interfaces:out-discards": "0",
+ "openconfig-interfaces:out-errors": "0",
+ "openconfig-interfaces:out-multicast-pkts": "217232",
+ "openconfig-interfaces:out-octets": "51749355",
+ "openconfig-interfaces:out-unicast-pkts": "416911"
+ }
+ }
+ ]
+ },
+ {
+ "timestamp": 0,
+ "update": [
+ {
+ "path": "network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state",
+ "val": {
+ "openconfig-network-instance:enabled": true,
+ "openconfig-network-instance:established-transitions": "0",
+ "openconfig-network-instance:last-established": "1625684802230601216",
+ "openconfig-network-instance:messages": {
+ "received": {
+ "UPDATE": "0"
+ },
+ "sent": {
+ "UPDATE": "0"
+ }
+ },
+ "openconfig-network-instance:neighbor-address": "192.168.255.2",
+ "openconfig-network-instance:peer-group": "EVPN-OVERLAY-PEERS",
+ "openconfig-network-instance:send-community": "NONE",
+ "openconfig-network-instance:session-state": "ACTIVE"
+ }
+ },
+ {
+ "path": "network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state",
+ "val": {
+ "openconfig-network-instance:enabled": true,
+ "openconfig-network-instance:established-transitions": "2",
+ "openconfig-network-instance:last-established": "1625740129181922304",
+ "openconfig-network-instance:messages": {
+ "received": {
+ "UPDATE": "2"
+ },
+ "sent": {
+ "UPDATE": "24"
+ }
+ },
+ "openconfig-network-instance:neighbor-address": "192.168.255.1",
+ "openconfig-network-instance:peer-group": "EVPN-OVERLAY-PEERS",
+ "openconfig-network-instance:send-community": "NONE",
+ "openconfig-network-instance:session-state": "ACTIVE"
+ }
+ }
+ ]
+ }
+ ]
+}
+
The file sub.py uses the +pygnmi python module and uses the gNMI Subscribe RPC
+ ++ +
{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-broadcast-pkts', 'val': 2}], 'timestamp': 1626462768674581749}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-discards', 'val': 0}], 'timestamp': 1626462768674597259}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-errors', 'val': 0}], 'timestamp': 1626462768674603747}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-fcs-errors', 'val': 0}], 'timestamp': 1626462768672465216}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-multicast-pkts', 'val': 189439}], 'timestamp': 1626462768674588779}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-octets', 'val': 48284395}], 'timestamp': 1626462768674553338}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-unicast-pkts', 'val': 416884}], 'timestamp': 1626462768674571889}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-broadcast-pkts', 'val': 14}], 'timestamp': 1626462768674624983}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-discards', 'val': 0}], 'timestamp': 1626462768674639908}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-errors', 'val': 0}], 'timestamp': 1626462768674645915}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-multicast-pkts', 'val': 217294}], 'timestamp': 1626599894372892660}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-octets', 'val': 51756949}], 'timestamp': 1626599894372858163}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-unicast-pkts', 'val': 416911}], 'timestamp': 1626462768674617475}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/enabled', 'val': True}], 'timestamp': 1626462768440845697}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/established-transitions', 'val': 0}], 'timestamp': 1626462768468632490}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/last-established', 'val': 1625684802230601216}], 'timestamp': 1626462768469284793}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/messages/received/UPDATE', 'val': 0}], 'timestamp': 1626462768421128387}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/messages/sent/UPDATE', 'val': 0}], 'timestamp': 1626462768421184402}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/neighbor-address', 'val': '192.168.255.2'}], 'timestamp': 1626462768421876850}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/peer-group', 'val': 'EVPN-OVERLAY-PEERS'}], 'timestamp': 1626462768439035722}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/send-community', 'val': 'NONE'}], 'timestamp': 1626462768419003214}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/session-state', 'val': 'ACTIVE'}], 'timestamp': 1626462768469145043}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/enabled', 'val': True}], 'timestamp': 1626462768428252812}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/established-transitions', 'val': 2}], 'timestamp': 1626462768470394508}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/last-established', 'val': 1625740129181922304}], 'timestamp': 1626462768469974563}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/messages/received/UPDATE', 'val': 2}], 'timestamp': 1626462768424768147}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/messages/sent/UPDATE', 'val': 24}], 'timestamp': 1626462768424826346}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/neighbor-address', 'val': '192.168.255.1'}], 'timestamp': 1626462768425586744}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/peer-group', 'val': 'EVPN-OVERLAY-PEERS'}], 'timestamp': 1626462768427044044}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/send-community', 'val': 'NONE'}], 'timestamp': 1626462768423035498}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/session-state', 'val': 'ACTIVE'}], 'timestamp': 1626462768469536321}}
+{'sync_response': True}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-broadcast-pkts', 'val': 2}], 'timestamp': 1626462768674581749}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-discards', 'val': 0}], 'timestamp': 1626462768674597259}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-errors', 'val': 0}], 'timestamp': 1626462768674603747}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-fcs-errors', 'val': 0}], 'timestamp': 1626462768672465216}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-multicast-pkts', 'val': 189439}], 'timestamp': 1626462768674588779}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-octets', 'val': 48284395}], 'timestamp': 1626462768674553338}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-unicast-pkts', 'val': 416884}], 'timestamp': 1626462768674571889}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-broadcast-pkts', 'val': 14}], 'timestamp': 1626462768674624983}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-discards', 'val': 0}], 'timestamp': 1626462768674639908}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-errors', 'val': 0}], 'timestamp': 1626462768674645915}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-multicast-pkts', 'val': 217299}], 'timestamp': 1626599904372340631}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-octets', 'val': 51757564}], 'timestamp': 1626599904372302101}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-unicast-pkts', 'val': 416911}], 'timestamp': 1626462768674617475}}
+{'sync_response': True}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/enabled', 'val': True}], 'timestamp': 1626462768440845697}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/established-transitions', 'val': 0}], 'timestamp': 1626462768468632490}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/last-established', 'val': 1625684802230601216}], 'timestamp': 1626462768469284793}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/messages/received/UPDATE', 'val': 0}], 'timestamp': 1626462768421128387}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/messages/sent/UPDATE', 'val': 0}], 'timestamp': 1626462768421184402}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/neighbor-address', 'val': '192.168.255.2'}], 'timestamp': 1626462768421876850}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/peer-group', 'val': 'EVPN-OVERLAY-PEERS'}], 'timestamp': 1626462768439035722}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/send-community', 'val': 'NONE'}], 'timestamp': 1626462768419003214}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/session-state', 'val': 'ACTIVE'}], 'timestamp': 1626462768469145043}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/enabled', 'val': True}], 'timestamp': 1626462768428252812}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/established-transitions', 'val': 2}], 'timestamp': 1626462768470394508}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/last-established', 'val': 1625740129181922304}], 'timestamp': 1626462768469974563}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/messages/received/UPDATE', 'val': 2}], 'timestamp': 1626462768424768147}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/messages/sent/UPDATE', 'val': 24}], 'timestamp': 1626462768424826346}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/neighbor-address', 'val': '192.168.255.1'}], 'timestamp': 1626462768425586744}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/peer-group', 'val': 'EVPN-OVERLAY-PEERS'}], 'timestamp': 1626462768427044044}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/send-community', 'val': 'NONE'}], 'timestamp': 1626462768423035498}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/session-state', 'val': 'ACTIVE'}], 'timestamp': 1626462768469536321}}
+{'sync_response': True}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-broadcast-pkts', 'val': 2}], 'timestamp': 1626462768674581749}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-discards', 'val': 0}], 'timestamp': 1626462768674597259}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-errors', 'val': 0}], 'timestamp': 1626462768674603747}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-fcs-errors', 'val': 0}], 'timestamp': 1626462768672465216}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-multicast-pkts', 'val': 189439}], 'timestamp': 1626462768674588779}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-octets', 'val': 48284395}], 'timestamp': 1626462768674553338}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/in-unicast-pkts', 'val': 416884}], 'timestamp': 1626462768674571889}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-broadcast-pkts', 'val': 14}], 'timestamp': 1626462768674624983}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-discards', 'val': 0}], 'timestamp': 1626462768674639908}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-errors', 'val': 0}], 'timestamp': 1626462768674645915}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-multicast-pkts', 'val': 217304}], 'timestamp': 1626599914374756337}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-octets', 'val': 51758179}], 'timestamp': 1626599914374727204}}
+{'update': {'update': [{'path': 'interfaces/interface[name=Ethernet1]/state/counters/out-unicast-pkts', 'val': 416911}], 'timestamp': 1626462768674617475}}
+{'sync_response': True}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/enabled', 'val': True}], 'timestamp': 1626462768440845697}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/established-transitions', 'val': 0}], 'timestamp': 1626462768468632490}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/last-established', 'val': 1625684802230601216}], 'timestamp': 1626462768469284793}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/messages/received/UPDATE', 'val': 0}], 'timestamp': 1626462768421128387}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/messages/sent/UPDATE', 'val': 0}], 'timestamp': 1626462768421184402}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/neighbor-address', 'val': '192.168.255.2'}], 'timestamp': 1626462768421876850}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/peer-group', 'val': 'EVPN-OVERLAY-PEERS'}], 'timestamp': 1626462768439035722}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/send-community', 'val': 'NONE'}], 'timestamp': 1626462768419003214}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.2]/state/session-state', 'val': 'ACTIVE'}], 'timestamp': 1626462768469145043}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/enabled', 'val': True}], 'timestamp': 1626462768428252812}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/established-transitions', 'val': 2}], 'timestamp': 1626462768470394508}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/last-established', 'val': 1625740129181922304}], 'timestamp': 1626462768469974563}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/messages/received/UPDATE', 'val': 2}], 'timestamp': 1626462768424768147}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/messages/sent/UPDATE', 'val': 24}], 'timestamp': 1626462768424826346}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/neighbor-address', 'val': '192.168.255.1'}], 'timestamp': 1626462768425586744}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/peer-group', 'val': 'EVPN-OVERLAY-PEERS'}], 'timestamp': 1626462768427044044}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/send-community', 'val': 'NONE'}], 'timestamp': 1626462768423035498}}
+{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[name=BGP][identifier=BGP]/bgp/neighbors/neighbor[neighbor-address=192.168.255.1]/state/session-state', 'val': 'ACTIVE'}], 'timestamp': 1626462768469536321}}
+
The file update.py uses the +pygnmi python module and uses the gNMI SET RPC (update)
+ +GET RPC, interface Ethernet1 config, before the update
+{
+ "notification": [
+ {
+ "timestamp": 0,
+ "update": [
+ {
+ "path": "interfaces/interface[name=Ethernet1]/config",
+ "val": {
+ "arista-intf-augments:load-interval": 300,
+ "openconfig-interfaces:description": "test1234",
+ "openconfig-interfaces:enabled": true,
+ "openconfig-interfaces:loopback-mode": false,
+ "openconfig-interfaces:mtu": 0,
+ "openconfig-interfaces:name": "Ethernet1",
+ "openconfig-interfaces:type": "iana-if-type:ethernetCsmacd",
+ "openconfig-vlan:tpid": "openconfig-vlan-types:TPID_0X8100"
+ }
+ }
+ ]
+ }
+ ]
+}
+
SET RPC, update, interface Ethernet1
+{'response': [{'path': 'interfaces/interface[name=Ethernet1]', 'op': 'UPDATE'}]}
+
+GET RPC, interface Ethernet1 config, after the update
+{
+ "notification": [
+ {
+ "timestamp": 0,
+ "update": [
+ {
+ "path": "interfaces/interface[name=Ethernet1]/config",
+ "val": {
+ "arista-intf-augments:load-interval": 300,
+ "openconfig-interfaces:description": "Test",
+ "openconfig-interfaces:enabled": true,
+ "openconfig-interfaces:loopback-mode": false,
+ "openconfig-interfaces:mtu": 0,
+ "openconfig-interfaces:name": "Ethernet1",
+ "openconfig-interfaces:type": "iana-if-type:ethernetCsmacd",
+ "openconfig-vlan:tpid": "openconfig-vlan-types:TPID_0X8100"
+ }
+ }
+ ]
+ }
+ ]
+}
+
The file delete.py uses the +pygnmi python module and uses the gNMI SET RPC (delete)
+ +output
+ + + + + + + + + +curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet1/config/description' \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure
+
Output:
+ +curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet1' \
+ --header 'Accept: application/yang-data+json' -u arista:arista \
+ --insecure | jq .'"openconfig-interfaces:state".counters."in-octets"'
+
Output:
+ +curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces' \
+ --header 'Accept: application/yang-data+json' -u arista:arista \
+ --insecure | jq .'"openconfig-interfaces:interface"[2].name'
+
Output:
+ +curl -X GET https://192.0.2.105:6020/restconf/data/system \
+ --header 'Accept: application/yang-data+json' -u arista:arista \
+ --insecure | jq .'"openconfig-system:config".hostname'
+
Output:
+ % Total % Received % Xferd Average Speed Time Time Time Current
+ Dload Upload Total Spent Left Speed
+100 66151 0 66151 0 0 284k 0 --:--:-- --:--:-- --:--:-- 284k
+"switch1"
+
curl -s GET 'https://192.0.2.100:5900/restconf/data/network-instances/network-instance=default/protocols/protocol=BGP,BGP/bgp/neighbors/neighbor=192.0.2.21/afi-safis/afi-safi=IPV4_UNICAST' \
+ --header 'Accept: application/yang-data+json' -u cvpadmin:arastra --insecure | jq
+
Output:
+{
+ "openconfig-network-instance:afi-safi-name": "openconfig-bgp-types:IPV4_UNICAST",
+ "openconfig-network-instance:config": {
+ "afi-safi-name": "openconfig-bgp-types:IPV4_UNICAST"
+ },
+ "openconfig-network-instance:state": {
+ "afi-safi-name": "openconfig-bgp-types:IPV4_UNICAST",
+ "prefixes": {
+ "arista-bgp-augments:best-ecmp-paths": 0,
+ "arista-bgp-augments:best-paths": 0,
+ "installed": 7,
+ "received": 7,
+ "sent": 7
+ }
+ }
+}
+
++NOTE: The protocol must have multiple keys, i.e.:
+protocol=BGP,BGP
, in this case, it's theidentifier
and +thename
of the protocol, if either of these is omitted; on the switch side in the Octa/OpenConfig agent logs +an error similar to the following would be generated:+
handler.go:95] ERROR mismatch between number of keys in [identifier name] and values present [BGP]
or +if are omitted the error message would be: +handler.go:95] ERROR failed to find key values after element "protocol" in "network-instances/network-instance=default/protocols/protocol
Tip: pyang can be useful to understand what keys each leaf requires, e.g:
+
pyang openconfig-network-instance.yang -f tree --tree-depth=4 | tail -n 4
+
+ | ...
+ +--rw protocols
+ +--rw protocol* [identifier name]
+ ...
+
curl --head 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet1' \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure
+
output
+ +Let's check before the change
+curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4/config' \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure
+
output
+{"openconfig-interfaces:description":"blabla","openconfig-interfaces:enabled":false,"arista-intf-augments:load-interval":300,"openconfig-interfaces:loopback-mode":false,"openconfig-interfaces:mtu":0,"openconfig-interfaces:name":"Ethernet4","openconfig-vlan:tpid":"openconfig-vlan-types:TPID_0X8100","openconfig-interfaces:type":"iana-if-type:ethernetCsmacd"}
+
Let's use the file interface.json
+ +output
+ +curl -X PUT https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4/config \
+ -H 'Content-Type: application/json' -u arista:arista -d @interface.json --insecure
+
output
+{"openconfig-interfaces:description":"restconf_test","openconfig-interfaces:enabled":true,"openconfig-interfaces:name":"Ethernet4"}
+
Let's verify after the change
+curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4/config' \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure
+
output
+{"openconfig-interfaces:description":"restconf_test","openconfig-interfaces:enabled":true,"arista-intf-augments:load-interval":300,"openconfig-interfaces:loopback-mode":false,"openconfig-interfaces:mtu":0,"openconfig-interfaces:name":"Ethernet4","openconfig-vlan:tpid":"openconfig-vlan-types:TPID_0X8100","openconfig-interfaces:type":"iana-if-type:ethernetCsmacd"}
+
curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4/config' \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure | jq .
+
output
+{
+ "openconfig-interfaces:description": "restconf_test",
+ "openconfig-interfaces:enabled": true,
+ "arista-intf-augments:load-interval": 300,
+ "openconfig-interfaces:loopback-mode": false,
+ "openconfig-interfaces:mtu": 0,
+ "openconfig-interfaces:name": "Ethernet4",
+ "openconfig-vlan:tpid": "openconfig-vlan-types:TPID_0X8100",
+ "openconfig-interfaces:type": "iana-if-type:ethernetCsmacd"
+}
+
Let's check before the change
+curl -X GET https://192.0.2.105:6020/restconf/data/system/config \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure
+
output
+ +curl -X GET https://192.0.2.105:6020/restconf/data/system \
+ --header 'Accept: application/yang-data+json' -u arista:arista \
+ --insecure | jq .'"openconfig-system:config".hostname'
+
output
+ % Total % Received % Xferd Average Speed Time Time Time Current
+ Dload Upload Total Spent Left Speed
+100 74748 0 74748 0 0 300k 0 --:--:-- --:--:-- --:--:-- 300k
+"DC1-LEAF1A"
+
curl -X PUT https://192.0.2.105:6020/restconf/data/system/config \
+ -H 'Content-Type: application/json' -u arista:arista \
+ -d '{"openconfig-system:hostname":"test"}' --insecure
+
output
+ +Let's verify after the change
+curl -X GET https://192.0.2.105:6020/restconf/data/system/config \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure
+
output
+ +Let's check before the change
+curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4' \
+ --header 'Accept: application/yang-data+json' -u arista:arista \
+ --insecure | jq .'"openconfig-interfaces:config"'
+
output
+{
+ "description": "",
+ "enabled": true,
+ "arista-intf-augments:load-interval": 300,
+ "loopback-mode": false,
+ "mtu": 0,
+ "name": "Ethernet4",
+ "openconfig-vlan:tpid": "openconfig-vlan-types:TPID_0X8100",
+ "type": "iana-if-type:ethernetCsmacd"
+}
+
curl -X POST https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4/config \
+ -H 'Content-Type: application/json' -u arista:arista \
+ -d '{"openconfig-interfaces:description":"restconf_test"}' --insecure
+
output
+ +curl -X POST https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4/config \
+ -H 'Content-Type: application/json' -u arista:arista \
+ -d '{"openconfig-interfaces:enabled":false}' --insecure
+
output
+ +Let's verify after the change
+curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4' \
+ --header 'Accept: application/yang-data+json' -u arista:arista \
+ --insecure | jq .'"openconfig-interfaces:config".description'
+
output
+ +curl -s GET 'https://192.0.2.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet4' \
+ --header 'Accept: application/yang-data+json' \
+ -u arista:arista --insecure | jq .'"openconfig-interfaces:config"'
+
output
+{
+ "description": "restconf_test",
+ "enabled": false,
+ "arista-intf-augments:load-interval": 300,
+ "loopback-mode": false,
+ "mtu": 0,
+ "name": "Ethernet4",
+ "openconfig-vlan:tpid": "openconfig-vlan-types:TPID_0X8100",
+ "type": "iana-if-type:ethernetCsmacd"
+}
+
Let's check before the change
+curl -s GET 'https://192.0.2.105:6020/restconf/data/ietf-interfaces:interfaces/interface=Loopback100' \
+ --header 'Accept: application/yang-data+json' -u arista:arista --insecure
+
output
+{"openconfig-interfaces:config":{"description":"test","enabled":true,"arista-intf-augments:load-interval":300,"loopback-mode":true,"name":"Loopback100","openconfig-vlan:tpid":"openconfig-vlan-types:TPID_0X8100","type":"iana-if-type:softwareLoopback"},"openconfig-interfaces:hold-time":{"config":{"down":0,"up":0},"state":{"down":0,"up":0}},"openconfig-interfaces:name":"Loopback100","openconfig-interfaces:state":{"enabled":true,"loopback-mode":false,"openconfig-vlan:tpid":"openconfig-vlan-types:TPID_0X8100"},"openconfig-interfaces:subinterfaces":{"subinterface":[{"config":{"description":"test","enabled":true,"index":0},"index":0,"openconfig-if-ip:ipv4":{"config":{"dhcp-client":false,"enabled":true,"mtu":1500},"state":{"dhcp-client":false,"enabled":true,"mtu":1500}},"openconfig-if-ip:ipv6":{"config":{"dhcp-client":false,"enabled":false,"mtu":1500},"state":{"dhcp-client":false,"enabled":false,"mtu":1500}},"state":{"enabled":true,"index":0}}]}}
+
RESTCONF is defined in the RFC 8040
+Please refer to this link
+The default RESTCONF port on Arista devices is TCP 6020.
+We need to change the default control-plane ACL on EOS in order to allow TCP 6020 (or the configured RESTCONF TCP port).
+Please refer to this link
+ + + + + + + + +$ python3
+Python 3.6.9 (default, Jan 26 2021, 15:33:00)
+[GCC 8.4.0] on linux
+Type "help", "copyright", "credits" or "license" for more information.
+>>> import requests
+>>> from requests.auth import HTTPBasicAuth
+>>> import json
+>>> USER = 'arista'
+>>> PASS = 'arista'
+>>> requests.packages.urllib3.disable_warnings()
+>>> headers = {'Content-Type': 'application/yang-data+json', 'Accept': 'application/yang-data+json'}
+>>> headers = {'Accept': 'application/yang-data+json'}
+>>> api_call = "https://10.73.1.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet1/state"
+>>> result = requests.get(api_call, auth=HTTPBasicAuth(USER, PASS), headers=headers, verify=False)
+>>> result.status_code
+200
+>>> result.ok
+True
+>>> result.url
+'https://10.73.1.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet1/state'
+>>> result.content
+b'{"openconfig-interfaces:admin-status":"UP","openconfig-interfaces:counters":{"in-broadcast-pkts":"0","in-discards":"0","in-errors":"0","in-fcs-errors":"0","in-multicast-pkts":"972","in-octets":"116602","in-unicast-pkts":"131","out-broadcast-pkts":"1","out-discards":"0","out-errors":"0","out-multicast-pkts":"1761","out-octets":"199997","out-unicast-pkts":"122"},"openconfig-interfaces:description":"restconf_test","openconfig-interfaces:enabled":true,"openconfig-platform-port:hardware-port":"Port1","openconfig-interfaces:ifindex":1,"arista-intf-augments:inactive":false,"openconfig-interfaces:last-change":"1624966430515012864","openconfig-interfaces:loopback-mode":false,"openconfig-interfaces:mtu":0,"openconfig-interfaces:name":"Ethernet1","openconfig-interfaces:oper-status":"UP","openconfig-vlan:tpid":"openconfig-vlan-types:TPID_0X8100","openconfig-interfaces:type":"iana-if-type:ethernetCsmacd"}\n'
+>>> result.json()
+{'openconfig-interfaces:admin-status': 'UP', 'openconfig-interfaces:counters': {'in-broadcast-pkts': '0', 'in-discards':
+'0', 'in-errors': '0', 'in-fcs-errors': '0', 'in-multicast-pkts': '972', 'in-octets': '116602', 'in-unicast-pkts':
+'131', 'out-broadcast-pkts': '1', 'out-discards': '0', 'out-errors': '0', 'out-multicast-pkts': '1761', 'out-octets':
+'199997', 'out-unicast-pkts': '122'}, 'openconfig-interfaces:description': 'restconf_test',
+'openconfig-interfaces:enabled': True, 'openconfig-platform-port:hardware-port': 'Port1',
+'openconfig-interfaces:ifindex': 1, 'arista-intf-augments:inactive': False, 'openconfig-interfaces:last-change':
+'1624966430515012864', 'openconfig-interfaces:loopback-mode': False, 'openconfig-interfaces:mtu': 0,
+'openconfig-interfaces:name': 'Ethernet1', 'openconfig-interfaces:oper-status': 'UP', 'openconfig-vlan:tpid':
+'openconfig-vlan-types:TPID_0X8100', 'openconfig-interfaces:type': 'iana-if-type:ethernetCsmacd'}
+>>> result.json()['openconfig-interfaces:oper-status']
+'UP'
+>>> result.json()['openconfig-interfaces:counters']['out-octets']
+'199997'
+>>> exit()
+
Execute the python script get_eth1_status.py
+ +output
+{'arista-intf-augments:inactive': False,
+ 'openconfig-interfaces:admin-status': 'UP',
+ 'openconfig-interfaces:counters': {'in-broadcast-pkts': '0',
+ 'in-discards': '0',
+ 'in-errors': '0',
+ 'in-fcs-errors': '0',
+ 'in-multicast-pkts': '1762',
+ 'in-octets': '202553',
+ 'in-unicast-pkts': '183',
+ 'out-broadcast-pkts': '1',
+ 'out-discards': '0',
+ 'out-errors': '0',
+ 'out-multicast-pkts': '2552',
+ 'out-octets': '284793',
+ 'out-unicast-pkts': '174'},
+ 'openconfig-interfaces:description': 'restconf_test',
+ 'openconfig-interfaces:enabled': True,
+ 'openconfig-interfaces:ifindex': 1,
+ 'openconfig-interfaces:last-change': '1624966430515012864',
+ 'openconfig-interfaces:loopback-mode': False,
+ 'openconfig-interfaces:mtu': 0,
+ 'openconfig-interfaces:name': 'Ethernet1',
+ 'openconfig-interfaces:oper-status': 'UP',
+ 'openconfig-interfaces:type': 'iana-if-type:ethernetCsmacd',
+ 'openconfig-platform-port:hardware-port': 'Port1',
+ 'openconfig-vlan:tpid': 'openconfig-vlan-types:TPID_0X8100'}
+
Execute the python script head.py
+ +output
+url is https://10.73.1.105:6020/restconf/data/openconfig-interfaces:interfaces/interface=Ethernet1/state
+status_code is 200
+headers are {'Content-Type': 'application/yang.data+json', 'Date': 'Sun, 18 Jul 2021 08:49:52 GMT'}
+content is b''
+
Execute the python script delete_lo100.py
+ +output (note the following has been formatted for readability.)
+get int lo100
+status_code is 200
+content is
+{'openconfig-interfaces:config': {'description': '222', 'enabled': True, 'arista-intf-augments:load-interval': 300,
+'loopback-mode': True, 'name': 'Loopback100', 'openconfig-vlan:tpid': 'openconfig-vlan-types:TPID_0X8100', 'type':
+'iana-if-type:softwareLoopback'}, 'openconfig-interfaces:hold-time': {'config': {'down': 0, 'up': 0}, 'state': {'down':
+0, 'up': 0}}, 'openconfig-interfaces:name': 'Loopback100', 'openconfig-interfaces:state': {'enabled': True,
+'loopback-mode': False, 'openconfig-vlan:tpid': 'openconfig-vlan-types:TPID_0X8100'},
+'openconfig-interfaces:subinterfaces': {'subinterface': [{'config': {'description': '222', 'enabled': True, 'index': 0},
+'index': 0, 'openconfig-if-ip:ipv4': {'config': {'dhcp-client': False, 'enabled': True, 'mtu': 1500}, 'state':
+{'dhcp-client': False, 'enabled': True, 'mtu': 1500}}, 'openconfig-if-ip:ipv6': {'config': {'dhcp-client': False,
+'enabled': False, 'mtu': 1500}, 'state': {'dhcp-client': False, 'enabled': False, 'mtu': 1500}}, 'state': {'enabled':
+True, 'index': 0}}]}}
+deleting int lo100
+status_code is 200
+
@={z zO5wJFr`Ue2)0Nj*M=Lpi4buHa^zN_w+lcDR;6404?V=AQn7l~1DV zQw%1LYdP*Kz$Vj>GcQ?c{6ECI48|kV{E^V$;{Ps<_)j>KOnMqa8%fm`mlwk-{RU9s zivQ{=#Ky-F0L|EPGchPOahn!|_q6*n4VcjZl+EP6F(yT&_ATensQn f^ HDZs6tBf4P|9X1fL#=QyW`em@$(Xk|1YX?m3Zb zAl|yl6E+?Hq=AwIfyi9S{FB0Ji2sxm668vF|5#3#qgy>v#L(5iV(Dlm!4D0fdGwG& z!e`fF=onJY*?M2wTxuWFtGJQROm7iL;3D0&*1KYBeeUy{FLu@f>ut1be$|-Omh-d? zJ9+*nagveDYFE^%Wc*tzmCWoWHL7$`kFdUemZH+qh%+id`#lJok+jsqCs`Z|{+RQ^ zx7=VtZG$lt3rA$en}t_*_LqSzO~i-cFM}&Sz^Y@s^bFJ^>q%=+EhP=qBrt8;IWFdZ zL=ckP5>*RnMp!HZ-9RX0(*5`aWbr %ik=PlwBRUZb`Sah&$hm4oWK8f%3hARp^X zC_> ^ZGMa&%r8vl$*~dl2SOPKpm+lYs&D;z_^6fg`|0P2|G39r4e=)j zZ88PwSvklEOA+)^>%{s(FS=y6yto{2f7J0IH>YX>mqMPnRLikf1^w4-t6&i&sHFJu z2&!<@9nC_`Z=1t4`5vu>dwl6f^yooRR#uQq1le1j0@XrDz$y4-t{OfHhCr3#*_+c& z ;oPX8wEcxVT45=kDQ-mE3mE~U>h{0*V1C3VoqF@Y?$u{Prl!7mZYt3d)*dS*v z;Q8g3C=}R;ax9N>0U6YN{u8X8!WcpWRpWxvBq$@T1JAHAYaCZqPHDmy_&%f4aFk6( zp@EJ`kd hpS1&<~L_ z>H<~*s@^J};+Z(30H%z)^-F(o4uF>SSmp*>PSXr|ljpWp)82#u8%ZLIygVP%^d8!T zYQU9dll6^v(_umMn92Q_fN@ntM1g9m3`$n;0T_8kE$Rpuk9(4n?*|Zdv)f0$^xtWE z+c>Q^QBDz(lk!nOoGmF%$lbRv;u>`ep(tcdfJcdflmBFF!g_5(H-b{SW*Jfm=i73E zHx2N8G5-yv#w!U`xB#Cr R {Zen0Obv8h4!Ks%Xq4_t{lBDHA?>*~b zw?j@VJ`1_fy(?&K|7Hun_^elRk{)?7x&rvf&!K3o vtZ_{bp!Qy*tNsu~tH+W-IiSYF55bjr&66lb~>qL#T2e!Bt|ZY1^8>jddi7 zPPD#8MAD65KcHR8LERGjha8rFgPcK z@dzV3) <80(h{vak>C2L {T=6M%>zWl1}$W}b#W}{VR z{;W6 2`avP}ICt@Y%<<*@3`A9WfRO+#@f8yOSwnP>>CU&eA(PIlN zo4Ien+A-mz>=CC^6OEvai4}Yt Sj4`ZqW{1@;|cx zz(t0)^30<0Z;BCvz-i#zwsIv$9pAX@Zv|)Q>p_Zzo>4!cX>?(?x|D$HalfnXj&r%_ z5SyEZXD6HW`?=6LdmoQ2a=S&C9nI}A&3%@Rak?t0>JLeQ1#irG?@oO8b}UjgGc!71 zi*X9C4dEpwI`eW2C|la*=IbjPRPTf6`}^smSE|F_IfojnZ&&jPXnL%y53G`Z(eW6E z4EOmQHv0Y6l~L^YMwP)WjG|;IQL$2p)A`XqLPELNpf8T}*5;uVyy750*|s-)^+>7T z1K~YNdJuS6YiT#g@;XA}cY_%>s?wMtFr5~2lhxj*`gZIrQ-p|#!yB=1i<)11w<|E1 zs@TSw1b*i*Q<+J9eXLmXag`w8VS0Jv2Mm`-kv<+AH6^;YJB8)Bs!Hi{PLNrd<3)W% zJAwUzT03onYe>K?1-Y0Hk&*lI*YRpA)smv3tY6`adAHXJ@*vNfzCx!Q%JNSD(y)W7 zuWYNlLuH4wXFN66r6>IcW&w44I02qGrk00}9I{MFe-vLfZ%|pEJmAd_!hiE>clqFu zM^VJ_RVa=_?;VEV+w!ZE2F4f HP4ewVo8{e+LIW$mBJtkwC`O`zY&Gx|7PW=)H`#?5RM#6)Uu*XLi zGXTn;O$q$=EPs?;S?2=3^Q2@|hp#+#O6P^TZ$4r8tc81xu7%4U-j; geb$ zgHd|N;a2}`pOn)>CJVCHs6swhA(peaFF&SWM@z3Pb~1MqkQ9~A^t^j`q>87;VV_RF zwKn05iai%4j=KaVw`ODdj0}!3j!5S|)Jue{;DDyxcC3jjL%PE*Urv`p)3Q7wS9O7Y zw8Rz6z$8V_6GdZ7;Xfdi_Ydc-EdEFd^WU-#Z5zgrX(Uxg9J6i}kr_LO^hI5 G7R(6LUpy6<;e zpN2MX)xAg>`@;3PI3yE*q3e0k7x195dsSVI*$RLd*Bjd$DGPGkoKG*$ V>V(M?3%q<2PthCw{C8ry5R_U^Nex8o@~>)mU)Q}9M3L2}5k$Vx}gpM E@3hs)|@095Z<|MFlZbi5bXC?mtS?lR|{^mBY_(;hp&kR_FN5 zoIL^2R;85gXm~ocEA{c#m-_enPWdfE(b`sD-q^~>AwQU?YrYyxcm;Hr$`$r#osz0I zais$eJarInj)#VY`juoto07)lsRQ=&SsAQb`i^zqmWI3sd`Ysx3(eJTQy9X&F=ojE z45G75YZYfPxG7oKttS(1ZM<@5G)eX}R`Kj);7NL7@uI^b@* aNwi=z 7zO$S&4Fd-)4VBoOXacet{GrAHY6Jq#i+ zzvk%cMm>up^ya&~d*3t+yh8Y(784@0EXVf|_z({nw!lb2GH7H0VMiap?TyJ`zM*jo z2Ry!W-;F8SEA!>AJhHJEQ3I)iKH(J_m!Y@fcwn2fy}jSh{Q-zBbnj89an6nK2Ne7r z)kk%uYwo-`h5jj{BOk!-u9SmIw-3C3X}xAD5K8If{Cu%3xq$7$Tc}p=Mu86*8V`A3 zm0}-te!6$@KK^>Q8J?c>5c-DFs}q?=t=WlRwU$bVJG=`VgC8YI`7P6OP
uBK4O{WjL3(IFB;_eI9^ EFx#2m^fCa2kyBU8PpTTOT9=Zr_Kj6-mjY>U0Yq#3owpYo#IhM?i)Bv znwyGxfg-eyV~H5!sT>E&$VPXL+wA|z%Eli%7i?t%CnL|^Y*?l_H4V_Oa_2MqJ+qRy z(IDG;6 EV2Xxc15m?5$etTtvjV~>h zx81j3>NqhZR6hVwj+T`V*OMEU<;O8ad1>({26X;A0yWF`;o`{i>q1H)eb6!d*M9Qi z#ax+!;7c$ufB%l)qHuJhWlpMJ!Vr5&SsMaJxHlNgeM{ea?LJ4J=AkC?VUN2tXay;$ z?L}aI_ RGTjOPzS;kU{s9j*depOkr!2N~Q zO;0#a)0TSEj8vE8=Y*S!eI F$bn%vS zh&_^JmiX5kwZ_eCpqSk=4*w|zfy*gNR3|#F0u}6q@^vBa# U}SbFU*CkG1D+ClQ?uSVVoxVF8Qb z&HlI)eSreN3+^#BPm4Xjom(Nd(m)ms!Q65o-T?XL4P;bd$X_biLmX%Bm1W@AUAhTs zt !%J>siF1 k5s6mkv`Fr=Y?|g+t+8Ui)H~^8PQAtK94o^eA75zgC0DCVDRk- zru)nrFUTtIE|WoTPCG1^cS?VCFuV ^01fw2?J1QRv;zk{BOZ*89$G=0GZSE43A&SJxngE*GzpqxP4q0)6k z@||2Ya`1xre&m$&hEgy2j&%?T`JvU -@2!S^G?nT)0AA#3y1Zamq9@3>BXi9kG%ACbs^+NC_3x$_HF zPVsR4Beu NN3AgLfq3Ts>HkoE1mz|IfNB_WHFsak#)_2?UV;Y;*pRssf%HvMCQfgA01G;$= zy?V`|s3W%&iRaT|JZA}9Ofq_>i_#+=pdK9HA&||Qfbm6F1j}({sJN To&GMQo81txy6#b)jXQzeR8M~{378K zPP66#ciD@~vDUmlI|F2*-{ y`HkpR*}1@rF$g6@?xK&kF^X8Cfp~s7 zWa2ef21y+!2T#MRs#H&x17-#N$7M|$HlM*pdt(H{0eiIg2WR<}cU)S#Ozu>j<#B+; zN CoU%Jh&{1Fg*>ED?a)UCG7k+sqhZfo{(PnOhH@Q^ z#KgfI%(rdr>(03MeRnk~-_D*5M^17(%k$^VwU5sjmf 5P_qILJ zg5uKG)X;ZrbXmg{K`(9|W?m+*vJ%A8(&pp*sXYG@ld{w$xe_6Kuq|P1+)z^Lo|^9U z;VFx|>YK!5{{5(dBo-e(;K$y98vL~R`@-)q*$w6EK)PyVK$M|aC*1ZcMEGc+VbTa) zr5aCw_?QLNEz9|W!AO%Katn_hNaq@zSC5-W{o=A~RAM?!$2!Javu+%%@4vhD!sE2S zsG$3m3tH6U>9TbI|FsxRNW{}J{IbGJK8Qg-{!2egoL{%AMFD9flk9~IwJe)80ULAv z1m^t) TT}f{6^K~@lc(v-Ogl=0SzeP40ws1*7NHfT zn_sC~mvjiSMt=7g>!Wsvddey`ZU7>tRGa)YY(z7kU}EV9VvB{22ZN%ABVw0xc_^ z-A{*`Wx7F`9Rf)_?W|M<>#z<0bqwSt>#ed+2GfNr4<8W3y^KMvpOx$D%>A4BqXidW zEH}-xQ_4Kz7n`+Qz 8zOtB3NMMAgSlDRB zeu#5mRj2?c9p1EoD-u^<{8q4G`JOz55?!0hlYtckBI^N=Q2u@4ENaxNIzMA4e=OE+ zt$dBKm6UpG2X9R2Qer$RQkN-5biEYkC!y2y<8>T9S(vx9CJ0B-xv89>5^tGW?`Ncj z&kmYK9}5Tn1&cftlz5<&yJ Bh2xOxt&FR3#HCTk7oF?j&S!cgCkia zJT~k{HmI-%9?KGFY 0+=J34!!}$Flf_U(;j-+}& zd@(e9wO6T0JWAVU @Xs{S;0IlIUnzZ2pVz=$L07(CVYKqG}yRI zCZ$gV3r>&a`hKF4E4ZuqU6XMiT@afES&h$_3J)bhZr$Vu=E&!oEFZePu$O)az07T# zTcQ@@>M!DW$KCDWqFt?gI8SYElC_UolvTPGbtdgzltjf9e+FMN!g0h^kKMfY%Td(M zZ=W22zeU&)j9}_3_PbZ<35r{B6dY2X%U&6ovCjZ6FW~(~{6UuFHB11LVcCpK;iiTP zQ(_K*GykY&iw+Hs;+(!ImrJkyokMGhz98%h&DT{oS@eEu{$I0G?Rs)Y3#hO+FOpsL zDK3K+@XP3m2fmcKVc|s?J4Ehg3D|)&Yt< r>g&ld-$IeD@PhEGzPMxWYvpjKbCJ7C7QR(3#|Bl z{|+9QnhC RtSU= zOrYRHikWq);9C*`;P&`>Y$9}R>CV$La(0eT&>>;$WqF8)mdJ!p(oJ-@ETE{ME^6Dh zGq2>PE9ygS0AsoEgEK!`@V5`2C6Tx&;Z)-S+23^Z7C}M65}2=(p-kj`9=$tr=@~SB zX4~F(BK`tiKK-S}MDd`ZM$3TXFiv^@Z`g_jX93;|H3CY~mts#6635$zf%=b}`Jkp1 z+@kDkug8w)FEY{Xs##3+`k!t$!FD?Ad=djULRXmxAJzH^l)INm{s>nrFY<+$$-j#d zKHfaT-t=1!(;@oq3K|+0v@tMw2-alup~kCo>3zm6s1k*bk &UMZee>T9{G2E5z@oMJl@`qR*N>LZm4=LX_qVceDH8FZ`Od2 VhY(gm*6Fip z9-Y$YDi|(^2)1%;rh<@ejODGA*onB%)fDPITJ<<-?~vl%+6XRAd)W2+!=IjE v3mZ@lcUY1UVH;S>BPkhnBIn!MzU@#H=zNyU=bceRMmxPo0;u zpr LcUNwf1%zl_cby4&uH{epJr>pc ~N#2jq258>^q6UzT}P!-VqV)c4l^)rV2-ho%fP zh|dZ0eg1i>(SGkvrY;{*@ux%(dg=8&??^YGuY4#?E(W}qQ``EZ_ND u~!Ms zd3>^e;kBg5#a{S}2}eJ151eD}%TjhbfEsS`k|;;5mZ)ETkYp)HTO7Ocs2Q8w_%r3e zia9~o+OeIn3+Jm6qI?;MRBnpN%_`q#+{a?!-h)kaRNKA3Ql$Xu!VN8-2pqsmldi(R ztdve^c7mnNz654{%C$KE)>SAa$;qS9wn}MUQ>E-$QddD1sybnw_lmYjV| 1_~2L+)Q!W{4Hb~ zqJQ>&@s7LM9xWWK*h?7Ls#xxN?Zd&$+?1yDs?gud>dXjAWICEelg4uo+Ep9e0z$`^ z2e 2lZ9tyl-VHLj@q7sPBU6uE>V^Dc X`%U|>DlEVfyaELDWenybm+c%AfzaI!o@hED&D zamssSaX!9SE|RV7jQmPPC5e;>DmQkn$esV`aetuLWT2?>3(=4$Ln)rhZ#Av8pJvlv ztDTa+7WaW1dXptGyRAbIGX!`S*BIGSMcN2(>C!^vJw$CfJ`Bmoo=L%?gry`X#W!4S zM6YlDuCB2gl%J_RBT78haCp&r$OF)MUuyKuVo<=OP3jkA*Y=QE=}N#+in7?lH4XL5 z-7ZswW8bE$>rll4qmCU{_BC&nb1glsL++&61+k%aa22T2t2o6l!UgOtKg32!7%!HJ z8EoDlJlX*E)y!PJ uuaFQ!s{|q;h=y*Ota%3gJTPZSc z=io}_c)!7;y=i-nU04*-sbFLi9 A&x?)(}ZOii-n`xBu){5FFK7M_DTqZ`5{e*m65ZuQ`3+8 zLEQgE*;~Iw`F_#D9}uKO5CoKNq`SL>p}R{$a;TxZ1Zin$q-*HzPN^BXyStk+zVCH@ z{c@fE;Cb%Yd+oK?UibE0te{ieGx{^B=2Tg}g%P>FL{1Tx+Dmi!mwdJMSnfi M8xr+ZgI}U+S%BC&*g<(u zqpI5}t9XuYl-@q2{?&2=LQ(VW>_hCnz-$Vt#J&?>O>5Wu5xojy$;_(WK6ml2`)H=D zXFam~YH{{!J(aV2`@x9l ;rw<;A$NkKUaN<6;$b83FT<9zyyQ(bW%vF7_UxYEr;h8n3}dYE9X0){bB;?~~2 z60pWO5xU^Kzp-RnJ `jhmiUS4@s|IQ>};h=cr;xAvKFOx zNP37N&nchRof#r$`GSkrZN(_CaT 0U0d4CKc@3wrTshB_gnMTNM)B+oE?D#Vk;kK(nsqs0RPQ+%V#K$ z*A*MaxaA&cWGgq5pp5l4iNJ|?K+G=%Yqz;Y3|yl8@cipP!**LIacD2{p*v{bVgV;p zr4%oI7TzF9*rX%n(k%fD9AQeE!*Qn5gfzZdzUL~ea%bupbmlaxz!j5d77Xs^Ql-B? z#j>@v(bL|}K1q~wwR{rb{w~o|; AbX=0rdPhj(iw(-rHjeSit5l+~{Idz5s(MJ>TE%gyZh zOX8q%f}CG> ai^oj0lS`SFT}n$xFCbFw&?h-19;+{csy? zu~;|L@ieWBEt7a5!8BV?I@^icTV=Ved$;-8seBt>&L72b1k_)SQ{^RFnyZuT1fF{_ z^wLjf4BKfj&wu2(K-^rnXI+@h9*QlFqq)Y>qJ5;LTs7;w-{^>Rkezmfb6=_rxTP!N z@F~z7oqqC_%JeWLVstmgn{qb3{bGqRIU0q&R1@GG?R()pe>tsekX)ZmMCC|8!wZWz zJp0^yGowyCQqIIQ5c+x8?FM|T@YRmvL1=o7Z^s-^gHw04o8#tA%CQ~+k!W_r7Bj+j z6{d Z0~s z?I-S|ErH Xr{j>IOe;?W;(XyOP5j)}hc9Ln*U|y#KJd zKK#O*C-9vY9edtE`j^Ea%J6drO;^@A!mLlA?r?&)aW55fFAmj)aY7jHU=Xb5pOoB7 z!2 eQV0?$jLNNDaHhXHr7HSPQDT|-z07_>g7zt=$kL$Z#DfxWjh+?M0--K?_3i} zHUUmw|Fgc$TjD=&h`c%H{z@Uppzf=;AZC*Pk`c(@+A#eMjp%cVDE&?%?B&NZA)xoe zZR4&4+K~f3JS(D{%H!ARYQl~dfo*3zMca*&y^Tljr2$!9uCLyDhc8~cGS3g^o88uy zch#QKKK*fxh!-uA*mi`ci>m;^$3a3QZx|>b!h^XYZv^kcy+Wm>&A{gas^oM-xP22t z-bOL*+Y6sLDK)J*35={;#%XG4xv2}F$1MeS aRT2((TheET}=a9mSwwO2H6IWXHk!9qyqrmA{9tgaA+&@{(g4l{8OPvf}F)A zy8rusRivoM;`>*2Yt$1iPEYrF1Y9f)Og?dD_Umm#V&8&kMq}OeP^`Y{juDMri7(Jg zD>{-|%=Rux$9!(Cpbg`P6G -5BxqF2$G#^|aPfEXRERBInVM1RMbBi`y7IPTfp(dEnYNUAK{v-u zKfx~8{F+j5bK1tDMGynA?P2j!H0;l#AsY#BW*=L_Px^VJXIcoZ=+kxAm~gJEj7(_6 zCQi}$y`b>(G&_{ZVuis050>j}{z)$xBc5LoRfq(m* 2X(#z{SmWaD3EEB#EazUU8xhWv4nv6yR_YtJF2IdFfrUJ95sc zR!ZDy=f#hyITiD!O5=1g3b!tyYC4 O$!d_9X@Tu>L@PyIX)=P39fX$o&R;#ySas#NI;-z0Lr_c zqM(A>a>Dp!+rP9LB%agh+3hd(Z(xPHiGCk1G9?2hKKn*0VM8O=8o@@Re+dVphZj=o z%aFgDPL4c0Jl13S4HSb`CACy3mG|53Z-W&@BN+=+nEy$vUwvF(C(A2<73SB)fJwPA z!lz;;-!39WVsg19Xn6-J`^ahKOb45Uiz`a)86K^jXDSOvUFte|{-~*&L?C#2iOwrA zuWsv 23pZ_VF|j+W)$`c@y|wo3 zDs1EKVRLv1LYau)VPft7NlrpEjQ({fF~(BsA~xhm4t6QgJk0)KX0^KV;vD^2k9LL< z=btZ_LiT#fB}eOxg}=Aop@==5xAhJ(lHi!YoKu8GR`Uvs^<-| KUk0Ck5SV${JGUQPYrQliH8+kaO#!3{dbAPl0J# z`zS}onx!kx;r!#o)lX687Z0=}ZQtTMsuox6RX0lqr+%_?H0xjP$+J)2%{ (F RgP49|9uUB6^1bx2#nVf5R75{@&JhKrY{9&TKnSD~zFh2J+1 zLyeD5u8+t>U;e0Ku p#jZH3bZ`zaf!3 z6rId-{c?MfGt2xD22Yt_4XUR2QF`&WFQbb^c=qe33uTH)z9^=1oldBR?oV_`h~X9k zx5oRz#ePko)1hIqu4@~7O?`gnhCbBiqleRXM617&5k?{3=!FerU%YIvm-u(EV$EHg z+4qErpC6pZ1U$xK(aWyGM`4OV7Zh0TW#U>yc;&`5WptR_w76fwG#4uy?OTd_yHLEd zSPMa U z)uznCh4#1Kd-9GMga XN;NGe(!$eG)cHU$)(Mg ze5=PG(@I^K&{Lh6-fPQ&_7`O*c)9x=?7c4kMmkYPpaGm#*Q)!KUn8BAF=d`*y0SGv z =O^v2;bD=e-;;s&kqlXj+5g?aGig$W^IG*QZa04*J-Ou= z7yqZX?)49%el@FI!3(KA6y&@4_MY&dLMnkA%*oeWFQR;N3&+j{i>O91MLNTnOp4cO zN6+Z0cUt{ tWfd=YNWWuKYsTdyTBAl&{2aKk>gIbdn zN6FWOX|mi)!t=%FP?v*CYt|$7Zh)AddDK+?%BG4y4lhU={lin&k>$^u_4XsD=7olb z;Wd$MPFM8W!~rz{qG!dgiyM3dGOGvY3vVZK72oB`4@W^3sPfcwKRa{n)oiFU9~G<% zX*+e+dg~EEVPgn!0K0RTs_7y+u0(Oe$Gnq}S$|}u8-@Ko20^S+lvEo&`NN* BAc;X{moyeZ083zP?ItRAn}*e^~JJEq&lHfE-S( z*ydTxf=`r7m5npw@`%b;{~O%#akT6UF5es!Xn9=RRD2)y^h^KI=4f{>b7Oo>(w6NX zOx9HS_(_e|#(8e!&EE5ho+#ePu51yiA+I2n8$|-<$xG&-6D_mq7m!?U9jx9~)6m&E zAKwm|qhc32axB=9bX{@_ogRB~!qRs%@eL{;4Oir7C4q-4y?pj!;eTaWe!0M-7QNV8 ztK^jL?rCT;Ugua-C)f%stzY#peGzZFczmZBh{YIbm;}}vo~hDl${29J$q>FS^bX!u z&5#|Ybimvi;jK>8>?bZds^)X|`3n{R)i_XS3ZvDj zAh*HJ<~CPWoNJdY;hdf1_rx@x;geqs_e^1yim$8*?9Cj+cTbs&hH{5Pg$l? ODI+j4U2!&!8u*GPqfi2R8iehE61L#h)*W%?o@Sidw_T$C$Y_-kGoPLSocwe5> zf-4B=c%PFpTIi-40Av2YA$b7Gb-hI~uC^ p<{-=J)L`njD@+)Aw#C9+*k8D4IuI zT5=FP8|