Discovering device configuration

The yang::NetconfDiscoveryResource scans a netconf device for the instances of one element — the entries of a yang list, or a single container — and reports each instance as a discovered resource on the orchestrator. Use it to explore the config and state of a device, and to inventory existing config (e.g. before onboarding it into a service model).

Quick start

Discover every port configured on a Nokia SR OS device:

import yang

yang::NetconfDiscoveryResource(
    name="ports",
    device="router-east",
    host="10.20.30.40",
    port=830,
    credentials=yang::Credentials(
        username_env_var="ROUTER_EAST_USERNAME",
        password_env_var="ROUTER_EAST_PASSWORD",
    ),
    module_mapping={
        "nokia-conf": "urn:nokia.com:sros:ns:yang:sr:conf",
    },
    filter="<filter xmlns='urn:ietf:params:xml:ns:netconf:base:1.0' type='subtree'><configure xmlns='urn:nokia.com:sros:ns:yang:sr:conf'><port><admin-state/><ethernet><mode/><encap-type/><mtu/></ethernet></port></configure></filter>",
    discovery_target="/nokia-conf:configure/nokia-conf:port[port-id]",
    discovered_name="port:{port_id}",
)

On every deploy of this resource, the handler sends a get rpc with the filter, splits the reply in one item per port entry and reports one discovered resource per port, e.g. yang::NetconfResource[router-east,name=port:1/1/c2/1] with values:

{
  "name": "port:1/1/c2/1",
  "device": "router-east",
  "host": "10.20.30.40",
  "port": 830,
  "discovered_params": {"port_id": "1/1/c2/1"},
  "filter": "<the subtree filter selecting only this port>",
  "xml": "<the config of this port, as returned by the device>"
}

The discovered resources can be browsed in the web console and queried through the GET /api/v2/discovered endpoint.

Attributes

Attribute

Description

name

Name of the discovery resource, unique per device

device

Device name, used as agent name. Use the same value as for the yang::NetconfResource resources of this device, so that the orchestrator can match discovered and managed resources

host, port

Management address and netconf port of the device (default port: 830)

credentials / credentials_v2

Credentials used to open the netconf session, as for the other yang resources

module_mapping

Mapping of module name to namespace uri, used to resolve the prefixes of the discovery_target

filter

A netconf subtree filter (rfc 6241), sent as-is in the get rpc. It defines the scope of the discovery and the leaves fetched for each instance

discovery_target

The path of the element whose instances are discovered (see below)

discovered_name

A name template, resolved for each discovered instance (see below)

retry_count, retry_interval

Retry behaviour of the netconf requests, as for yang::NetconfResource

huge_tree

Enable XML huge tree support, for very large replies

The discovery target

The discovery_target is a path of slash-separated, qualified tags pointing at the element whose instances are discovered. The prefixes are module names, resolved through the module_mapping. Every yang list on the path that is enumerated (rather than pinned to one entry by the filter) declares the names of its key leaves with a bracket suffix:

/nokia-conf:configure/nokia-conf:port[port-id]

This is a plain path, not an xpath: the brackets declare key names, never values. A few rules:

  • Multi-key lists declare all their keys in one bracket, comma-separated: dzs:rule[group-index,member-index].

  • Nested lists: when the target list is nested inside another list, the enclosing list must either be pinned in the filter (a content match node selects one entry, e.g. <service-name>vprn-1</service-name> — nothing to declare), or be enumerated as well, with its own bracket suffix. The keys of every enumerated level become template variables:

    /nokia-conf:configure/nokia-conf:service/nokia-conf:vprn[service-name]/nokia-conf:interface[interface-name]
    
  • Single container: when the last segment declares no keys, the target is a plain container and exactly one resource is discovered (e.g. expose the whole /configure/system subtree of every device as one discovered resource):

    /nokia-conf:configure/nokia-conf:system
    

The filter must contain the target path (exactly one element per level). The selection leaves of the declared keys are added to the filter automatically when missing, so the device always returns the key values.

The discovered name

The discovered_name is a python format template, resolved for each discovered instance with the key values of the entry (and of its enumerated enclosing entries). The variable names are the key leaf names, normalized to valid identifiers: - and . are replaced by _ (port-idport_id).

The resolved name becomes the id of the discovered resource: yang::NetconfResource[<device>,name=<resolved discovered_name>]. It must be unique per instance: use enough parameters in the template, the handler fails otherwise.

Everything is validated when the resource is exported: the target path syntax and its presence in the filter, the uniqueness of the (normalized) key names and the template variables. A compile/export fails early with an actionable message instead of failing on the agent.

Discovered resources lifecycle

  • Each run reports the current instances and deletes the resources reported by its previous runs: entries that disappeared from the device are cleaned up, entries still present are refreshed.

  • Several discovery resources can coexist on the same device (e.g. one for ports, one for vprns): each one only cleans up its own discoveries.

  • The discovered resource ids reuse the yang::NetconfResource entity type and the agent of the discovery resource. When a managed resource with the same id exists (the discovered entry got onboarded), the orchestrator links both: the managed filter of the discovered resources api and the web console rely on this.

Onboarding discovered config

The values of each discovered resource mirror the inputs of a yang::NetconfResource:

  • discovered_params holds the identity of the instance (the key values),

  • filter is a subtree filter restricted to this single instance,

  • xml is the instance config as returned by the device.

A typical onboarding flow: discover the existing entries, match the discovered_params against the inventory (or use them as service identifiers), and instantiate the service model for each entry. Once the service deploys a yang::NetconfResource named after the same discovered_name, the discovered resource shows up as managed.

Discovering state

Discovering the state of the devices works exactly like discovering their config. The get rpc returns config and operational state: point the filter (and the discovery_target) at a state subtree (the config false; part of the yang models) to inventory operational data.

For example, discover the interfaces of the Base router on a Nokia SR OS device, with their operational status:

module_mapping   = {"nokia-state": "urn:nokia.com:sros:ns:yang:sr:state"}
filter           = <filter xmlns='urn:ietf:params:xml:ns:netconf:base:1.0' type='subtree'>
                     <state xmlns='urn:nokia.com:sros:ns:yang:sr:state'>
                       <router><router-name>Base</router-name>
                         <interface><interface-name/><oper-state/></interface>
                       </router>
                     </state>
                   </filter>
discovery_target = /nokia-state:state/nokia-state:router[router-name]/nokia-state:interface[interface-name]
discovered_name  = state:interface:{router_name}:{interface_name}

Each discovered resource then holds the operational leaves of one interface in its xml value (e.g. <oper-state>up</oper-state>). Config and state subtrees can also be combined in one inventory by deploying one discovery resource per subtree.

Limitations

  • Netconf only (no gnmi/restconf discovery yet).

  • One discovery resource discovers the instances of one element. Deploy several discovery resources to scan several lists.