Cisco Nexus 3000 and 9000 Series NX-API REST SDK User Guide and API Reference, Release 9.2(x)

Introduction

NX-API REST brings Model Driven Programmability (MDP) to standalone (non-APIC-based fabric) Nexus family switches. In model-driven architectures, software maintains a complete, explicit representation of the administrative and operational state of the system (the model) and performs actions only as side-effects of mutations of model entities.

This model is a formal specification understood by network planners and developers that is rendered into a running system. Furthermore, this object model is made available through standard Representational State Transfer (REST) interfaces, making it easier to access and manipulate the object model, and hence, the configuration and runtime state of the system.

The operational aspects of the modeling include statistics, faults and events – i.e. each of these would also have a model representation that is accessible programmatically to query the health of the system. In addition, the northbound management clients get notified about faults and events in a proactive manner once they subscribe to interested events.

Supported Platforms

NX-API REST is supported on the following platforms:

  • Cisco Nexus 3000 Series platforms with 8 GB or greater memory
  • All Cisco Nexus 9000 series platforms

Challenges with Current Approaches to Network Programmability

Most networks in use today were built on hardware with tightly coupled software intended to be managed and administered through the command-line interface (CLI).

These systems worked well in a world of static network configurations, static workloads, and predictable slower change rates for application scaling. As data center networks have been virtualized and begun moving to cloud and agile IT models, this model is no longer the optimal method.

Therefore, vendors are working to layer programmability onto existing offerings and device operating systems - for example, improving the accessibility of the CLIs by making them available outside of the switch by using HTTP/HTTPS and using JSON/XML payloads.

Although this approach increases capabilities, it is not an ideal method for incorporating programmability. The CLI based programming, whether locally on switch or remotely using HTTP/HTTPS, is still synchronous, proprietary, order dependent and sequential. Hence automating using CLI makes the task harder.

Cisco NX-API-REST Programmability with Object-Oriented Data Model and REST APIs

Cisco has taken a foundational approach to building a programmable network infrastructure with the Cisco ACI (Application Centric Infrastructure) solution. This infrastructure operates as a single system at the fabric level, controlled by the centralized Cisco Application Policy Infrastructure Controller (APIC).

The NX-API-REST model borrows several concepts from Cisco ACI and makes them available for non-ACI based standalone Nexus fabric environment. Like ACI, it uses an object-oriented eventual consistency model based on promise theory. Promise theory is based on scalable control of intelligent objects rather than more traditional imperative models, which can be thought of as a top-down management system. In this system, the central manager must be aware of both the configuration commands of underlying objects and the current state of those objects.

Promise theory, in contrast, relies on the underlying objects to handle configuration state changes initiated by the management agent itself as "desired state changes." The syntactically and semantically valid configuration objects are accepted into the system and their actual deployment is done in an asynchronous manner. The objects are then responsible for passing exceptions or faults back to the management system. This approach reduces the burden and complexity of the management system and allows greater scale.

Models present an opportunity to standardize the same, which in turn, makes them portable across platforms belonging to a given vendor or different vendors.
Models allow access of the same consistent configuration and management data via different protocols like CLI, NETCONF, RESTCONF, standard RESTful access, etc., using different encoding mechanisms (JSON, XML etc.). They also allow faster introduction of these protocols/encodings in the northbound direction as underlying the model and all the software behind it is agnostic to these upper layers.

YANG Data Modeling

YANG is a data modeling language that supports data models for the NETCONF protocol. (The NETCONF protocol supports network configuration management.)

YANG provides a way to define the objects and data in NETCONF requests and replies. YANG models the network configuration, operational, and RPC data; and it provides semantics to better define NETCONF data in terms of constraints, reusable structures, and built-in/derived types.

For more details about YANG data modeling, visit YANG Central https://www.yang-central.org.

NX-API-REST Modeled Objects

In the Cisco NX-API-REST framework, configuration and state information of the switch is stored in a hierarchical tree structure known as the management information tree (MIT), which is accessible through the API. One can make changes on a single object or an object subtree. Each node in the MIT represents a managed object or group of objects. These objects are organized in a hierarchical way, creating logical object containers. Figure 1 depicts the logical hierarchy of the MIT object model.

The NX-API-REST uses an information-model-based architecture in which the model describes all the information that can be controlled by a management process. Object instances are referred to as managed objects (MOs). Every managed object in the system can be identified by a unique distinguished name (DN). This approach allows the object to be referred to globally.

The NX-API-REST API operates in forgiving mode, which means that missing attributes are substituted with default values (if applicable) that are maintained in the internal data management engine (DME). The DME validates and rejects incorrect attributes. The API is also atomic. If multiple MOs are being configured, and any of the MOs cannot be configured, the API stops its operation. It returns the configuration to its prior state, stops the API operation that listens for API requests, and returns an error code.

Full event subscription is enabled. When any MO is created, changed, or deleted because of a user- or system-initiated action, an event is generated. With an API query, you can create a subscription to any future changes in the results of that query.

In addition to its distinguished name, each object can be referred to by its relative name (RN). The relative name identifies an object relative to its parent object. Any given object's distinguished name is derived from its own relative name appended to its parent object's distinguished name. Distinguished names are directly mapped to URLs. Either the relative name or the distinguished name can be used to access an object, dependent on the current location in the MIT. The relationship among managed objects, relative names, and distinguished names is shown in figure 2.

The above figure depicts the distinguished name, which uniquely represents any given managed object instance, and the relative name, which represents it locally underneath its parent managed object. All objects in the tree exist under the root object.

Because of the hierarchical nature of the tree and the attribute system used to identify object classes, the tree can be queried in several ways for managed object information. Queries can be performed on an object itself through its distinguished name, on a class of objects, or on a tree-level, discovering all members of an object.

For all MIT queries, one can optionally return the entire subtree or a partial subtree. Additionally, the role-based access control (RBAC) mechanism in the system dictates which objects are returned; only the objects that the user has rights to view will ever be returned.

Managed-Object Properties

Managed objects in Cisco NX-API-REST contain properties that define the managed object. Properties in a managed object are divided into chunks managed by given processes within the operating system. Any given object may have several processes that access it. All these properties together are compiled at runtime and presented to the user as a single object. Figure 2 below shows an example of this relationship.

In Figure 3, the example object has three processes that write to property chunks in the object. The Data Management Engine (DME), which is the interface between the manageability agent (thus the user) and the object, the Port Manager, which handles port configuration, and the Spanning Tree Protocol (STP) all interact with chunks of this object. The object itself is presented to the user through the API as a single entity compiled at runtime.

Starting with Cisco NX-OS 7.0(3)I5(2), the managed objects in Cisco NX-API-REST are documented in the Cisco NX-API Model Reference document https://developer.cisco.com/site/nx-os/docs/nexus-model-reference/

For information about using the payloads, see the Cisco Nexus 9000 Series NX-OS Programmability Guide
https://www.cisco.com/c/en/us/support/switches/nexus-9000-series-switches/products-programming-reference-guides-list.html.

Accessing the Object Data through REST Interfaces

REST is a software architecture style for distributed systems such as the World Wide Web. REST has emerged over the past few years as a predominant web service design model. REST has increasingly displaced other design models such as Simple Object Access Protocol (SOAP) and Web Services Description Language (WSDL) due to its simpler style. The Cisco NX-API-REST supports REST interfaces for programmatic access to Nexus switches.

REST is a collection of resources:

  • The base universal resource identifier (URI) for the web service, such as http://example.com/resources/
  • The Internet media type of the data supported by the web service; often JSON, XML, or YAML, but it can be any other valid Internet media type.
  • The set of operations supported by the web service using HTTP methods (for example, GET, PUT, POST, or DELETE )

Standard HTTP requests have the following semantics:

  • POST: Target domain name, class, and options specify roots of subtrees at which modifications are applied. Data carried in the request is in the form of structured text (XML or JSON) subtrees. You can, therefore, specify a parent tree node target and affect N subtrees under that node. POST also can run methods on objects in scope.
  • GET: Specify retrieval of objects in the scope of the URL and the options provided.
    Configuration of the network using REST calls doesn’t require a deep understanding of the object tree; one can easily change sample configurations and reapply them.

REST calls can be sent in a variety of ways. The most common use:

  • POSTMAN with a Chrome browser: This popular tool https://www.getpostman.com/ makes sending REST calls very easy.
  • Python scripts: You will most commonly use Python scripts for very large configurations that you want to create rapidly, and that you may have already tested individually using POSTMAN or cURL.
  • Scripts in general
  • Automation tools: For instance, one can use Cisco UCS Director or Cisco Intelligent Automation for Cloud (IAC).

The object-based information model of Cisco NXAPI-REST makes it a very good fit for REST interfaces: URLs and URIs map directly to distinguished names identifying objects on the tree, and any data on the MIT can be described as a self-contained structured text tree document encoded in XML or JavaScript Object Notation (JSON).

The objects have parent-child relationships that are identified using distinguished names and properties, which are read and modified by a set of create, read, update, and delete (CRUD) operations.

Objects can be accessed at their well-defined address, their REST URLs, using standard HTTP commands for retrieval and manipulation of Cisco NX-API-REST object data.

The URL format used can be represented as follows:
<system>/api/[mo|class]/[dn|class][:method].[xml|json]?{options}

The various building blocks of the preceding URL are as follows:

  • System: System identifier; an IP address or DNS-resolvable host name
  • mo | class: Indication of whether this is a managed object or tree (MIT) or class-level query
  • class: Managed-object class (as specified in the information model) of the objects queried; the class name is represented as
  • dn: Distinguished name (unique hierarchical name of the object in the MIT tree) of the object queried
  • method: Optional indication of the method being invoked on the object; applies only to POST requests
  • xml | json: Encoding format
  • options: Query options, filters, and arguments

The typical sequence of configuration is:

  1. Authenticate: Call https://<IP of Nexus switch>/api/aaaLogin.xml with a payload that in XML is <aaaUser name='username' pwd= 'password'/>. This call returns a cookie value that the browser uses for the next calls.

  2. Send POST to apply the configuration: The URL of the POST message varies depending on the object, the following is an example: https://<IP of Nexus switch>/api/mo/sys/bgp/inst.json, where api indicates that this call is to the API, mo indicates that this call is to modify a managed object, bgp/inst refers to the BGP instance, and .json indicates that the payload is in JSON format. If the end of URL were .xml, that would mean that the payload is in XML format.

  3. Verify the HTTP status code: one should want a response of 200 OK.
    With the capability to address and access an individual object or a class of objects with the REST URL, one can achieve complete programmatic access to the entire object tree and, thereby, to the entire system.

With the capability to address and access an individual object or a class of objects with the REST URL, one can achieve complete programmatic access to the entire object tree and, thereby, to the entire system.

Subscribing to Query Results

When an API query is performed, there is an option to create a subscription to any future changes in the results of that query that occur during your active API session. When any MO is created, changed, or deleted because of a user- or system-initiated action, an event is generated. If that event changes the results of an active subscribed query, the APIC generates a push notification to the API client that created the subscription.

Opening a WebSocket

The API subscription feature uses the WebSocket protocol (RFC 6455) to implement a two-way connection with the API client through which the API can send unsolicited notification messages to the client. To establish this notification channel, you must first open a WebSocket connection with the API. Only a single WebSocket connection is needed to support multiple query subscriptions with multiple NX-API-REST instances. The WebSocket connection is dependent on API session connection, and closes when the API session ends.

The WebSocket connection is typically opened by a JavaScript method in an HTML5-compliant browser, as in the following example:

var Socket = new WebSocket(https://<IP_Address>/socket%TOKEN%);

In the URI, the %TOKEN% is the current API session token (cookie).

After the WebSocket connection is established, it is not necessary to resend the API session token when the API session is refreshed.

Note:
- Before subscribing to an event, be sure you have at least one active WebSocket connection.
- Closing the WebSocket does not remove the subscription from the subscriptionMap. For deleting a subscription, see Deleting the Subscription.

Creating a Subscription

Creating a Subscription
GET https://<IP_Address>/api/mo/sys/intf/phys-[eth1/3].json?subscription=yes&query-target=subtree
{
    'totalCount': '25',
    'subscriptionId': '18374686492539748353',
    'imdata': [{
            'ethpmHwIfDetails': {
                'attributes': {
                    'dn': 'sys/intf/phys-[eth1/3]/hwifdetails',
                    'sPort': '0',
                    'slice': '0',
                    'vif': '3'
                }
            }
        }, {
            'ethpmFcot': {
                'attributes': {
                    'baseResvd1': '0',
                    'baseResvd2': '0',
                    'baseResvd3': '1',
                    'baseResvd4': '65,12,193',
                    'brIn100MHz': '13',
                    'brMaxMargin': '0',
                    'brMinMargin': '0',
                    'ccex': '233',
                    'ccid': '26',
                    'connectType': '0',
                    'dateCode': '11012001',
                    'description': '',
                    'diagMonType': '0',
                    'distIn100mFor9u': '0',
                    'distIn10mFor50u': '0',
                    'distIn10mFor60u': '0',
                    'distIn1mForCu': '100',
                    'distInKmFor9u': '0',
                    'dn': 'sys/intf/phys-[eth1/3]/phys/fcot',
                    'eid': 'unknown',
                    'encoding': '1',
                    'enhOption': '0',
                    'extOption': '0,16',
                    'fCTxType': '33',
                    'fcotNum': '19',
                    'fcotType': '8',
                    'flags': 'ok',
                    'gigEthCC': '8',
                    'isFcotPresent': 'yes',
                    'maxSpeed': '4',
                    'minSpeed': '4',
                    'partNumber': '',
                    'sff8472Compl': '0',
                    'state': 'inserted',
                    'type': 'sfp',
                    'typeName': '1000base-T',
                    'vendorData': '0,0,14,76,224,254,137,178,26,53,86,22,232,237,165,223,210,23,75,0,0,0,0,0,0,0,0,0,254,249,76,125',
                    'vendorId': '0,0,0',
                    'vendorName': 'CISCO-METHODE',
                    'vendorPn': 'SP7041-E',
                    'vendorRev': 'E',
                    'vendorSn': 'MTC150303LW',
                    'versionId': '',
                    'xcvrCode': '0,0,0,8,0,0,0,0',
                    'xcvrExtId': '4',
                    'xcvrId': '3'
                }
            }
        }, {
            'ethpmPortCap': {
                'attributes': {
                    'autoneg': '1',
                    'channel': '1',
                    'cosRewrite': '1',
                    'ctsCapable': '0',
                    'dn': 'sys/intf/phys-[eth1/3]/phys/portcap',
                    'duplex': 'full',
                    'eeeCapVal': '0',
                    'eeeFlapFlags': '0',
                    'eeeWakeTimes10g': '0,0,0',
                    'fcotCapable': '1',
                    'id': 'unspecified',
                    'linkDebounce': '1',
                    'linkDebounceTime': '50',
                    'mdix': '0',
                    'model': '103,98,105,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0',
                    'portCap': '247463936',
                    'portGroup': '2',
                    'portGrpMbrs': '3',
                    'protoSupport': '553648147',
                    'qosRxPrio': '0',
                    'qosRxQueue': '0',
                    'qosRxThold': '0',
                    'qosTxPrio': '0',
                    'qosTxQueue': '8',
                    'qosTxThold': '0',
                    'rateMode': '1',
                    'rxFlowControl': '7',
                    'span': '1',
                    'speed': '1000,10000',
                    'suppression': '1',
                    'tosRewrite': '1',
                    'trunkEncap': '1',
                    'txFlowControl': '7',
                    'type': '49,48,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0',
                    'udld': '1'
                }
            }
        }, {
            'ethpmPhysIf': {
                'attributes': {
                    'accessVlan': 'vlan-1',
                    'adminSt': 'up',
                    'allowedVlans': '',
                    'backplaneMac': 'A4:6C:2A:AC:42:EA',
                    'bundleBupId': '3',
                    'bundleIndex': 'unspecified',
                    'cachedUserCfgdFlags': 'admin_layer,admin_state',
                    'cfgAccessVlan': 'vlan-1',
                    'cfgNativeVlan': 'vlan-1',
                    'childAction': '',
                    'currErrIndex': '4294967295',
                    'diags': 'none',
                    'dn': 'sys/intf/phys-[eth1/3]/phys',
                    'dynamicVlan': 'no',
                    'encap': '3',
                    'errDisTimerRunning': 'no',
                    'errVlans': '',
                    'gport': '134219795',
                    'ifIndex': '436208640',
                    'intfT': 'phy',
                    'iod': '217',
                    'lastErrors': '0,0,0,0',
                    'lastLinkStChg': '2018-10-18T23:43:56.274+00:00',
                    'media': '2',
                    'modTs': 'never',
                    'nativeVlan': 'vlan-1',
                    'numOfSI': '0',
                    'operAutoNeg': 'on',
                    'operBitset': '3-4,13',
                    'operDceMode': 'edge',
                    'operDescr': '',
                    'operDuplex': 'full',
                    'operEEERxWkTime': '0',
                    'operEEEState': 'not-applicable',
                    'operEEETxWkTime': '0',
                    'operErrDisQual': 'up',
                    'operFECMode': '0',
                    'operFlowCtrl': '',
                    'operLinkDebounce': '100',
                    'operMdix': 'auto',
                    'operMode': 'access',
                    'operMtu': '1500',
                    'operPhyEnSt': 'unknown',
                    'operRouterMac': '74:A2:E6:C6:79:FF',
                    'operSpeed': '1G',
                    'operSt': 'up',
                    'operStQual': 'none',
                    'operStQualCode': '0',
                    'operTrunkStatus': 'not-trunking',
                    'operVlans': '1',
                    'persistentOnReload': 'false',
                    'portCfgWaitFlags': '0',
                    'primaryVlan': 'vlan-1',
                    'resetCtr': '2',
                    'shareState': 'dedicated',
                    'siList': '',
                    'status': '',
                    'txT': 'unknown',
                    'usage': '',
                    'userCfgdFlags': 'admin_layer,admin_state',
                    'vdcId': '1'
                }
            }
        }, {
            'l1EeeP': {
                'attributes': {
                    'childAction': '',
                    'descr': '',
                    'dn': 'sys/intf/phys-[eth1/3]/eeep',
                    'eeeLat': 'variable',
                    'eeeLpi': 'aggressive',
                    'eeeState': 'not-applicable',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'name': '',
                    'persistentOnReload': 'true',
                    'status': ''
                }
            }
        }, {
            'l1LoadP': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/loadp',
                    'ethpmCfgFailedBmp': '',
                    'ethpmCfgFailedTs': '00:00:00:00.000',
                    'ethpmCfgState': '0',
                    'loadIntvl1': '30',
                    'loadIntvl2': '300',
                    'loadIntvl3': '0',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'persistentOnReload': 'true',
                    'status': ''
                }
            }
        }, {
            'l1PhysIfExtended': {
                'attributes': {
                    'allowMultiTag': 'disable',
                    'bufferBoost': 'enable',
                    'childAction': '',
                    'descr': '',
                    'dn': 'sys/intf/phys-[eth1/3]/physExtd',
                    'flowCtrl': '',
                    'id': 'eth1/3',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'name': '',
                    'persistentOnReload': 'true',
                    'portTypeFabric': 'no',
                    'routerMacIpv6Extract': 'disable',
                    'status': '',
                    'stormCtrlAct': '',
                    'stormCtrlBCastLevel': '100.000000',
                    'stormCtrlBCastPPS': '4294967295',
                    'stormCtrlMCastLevel': '100.000000',
                    'stormCtrlMCastPPS': '4294967295',
                    'stormCtrlUCastLevel': '100.000000',
                    'stormCtrlUCastPPS': '4294967295',
                    'switchportBlock': '',
                    'switchportMacLearn': 'enable',
                    'switchportVirtualEthernetBridge': 'disable'
                }
            }
        }, {
            'l1RsCdpIfPolCons': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rscdpIfPolCons',
                    'forceResolve': 'no',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'rType': 'mo',
                    'state': 'formed',
                    'stateQual': 'none',
                    'status': '',
                    'tCl': 'cdpIfPol',
                    'tDn': 'uni/infra/cdpIfP-default',
                    'tType': 'mo'
                }
            }
        }, {
            'l1RsHIfPolCons': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rshIfPolCons',
                    'forceResolve': 'no',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'rType': 'mo',
                    'state': 'formed',
                    'stateQual': 'none',
                    'status': '',
                    'tCl': 'fabricHIfPol',
                    'tDn': 'uni/infra/hintfpol-default',
                    'tType': 'mo'
                }
            }
        }, {
            'l1RsStormctrlIfPolCons': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rsstormctrlIfPolCons',
                    'forceResolve': 'no',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'rType': 'mo',
                    'state': 'formed',
                    'stateQual': 'none',
                    'status': '',
                    'tCl': 'stormctrlIfPol',
                    'tDn': 'uni/infra/stormctrlifp-default',
                    'tType': 'mo'
                }
            }
        }, {
            'l1RsStpIfPolCons': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rsstpIfPolCons',
                    'forceResolve': 'no',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'rType': 'mo',
                    'state': 'formed',
                    'stateQual': 'none',
                    'status': '',
                    'tCl': 'stpIfPol',
                    'tDn': 'uni/infra/ifpol-default',
                    'tType': 'mo'
                }
            }
        }, {
            'l1RtEthIf': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rtl2EthIf-[sys/lacp/inst/if-[eth1/3]]',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'status': '',
                    'tCl': 'lacpIf',
                    'tDn': 'sys/lacp/inst/if-[eth1/3]',
                    'tSKey': 'eth1/3'
                }
            }
        }, {
            'l1RtEthIf': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rtl2EthIf-[sys/cdp/inst/if-[eth1/3]]',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'status': '',
                    'tCl': 'cdpIf',
                    'tDn': 'sys/cdp/inst/if-[eth1/3]',
                    'tSKey': 'eth1/3'
                }
            }
        }, {
            'l1RtIoPPhysConf': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rtioPPhysConf',
                    'modTs': '2018-10-18T19:32:07.068+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'status': '',
                    'tCl': 'eqptLeafP',
                    'tDn': 'sys/ch/lcslot-1/lc/leafport-3'
                }
            }
        }, {
            'l1StormCtrlP': {
                'attributes': {
                    'burstPps': '4294967295',
                    'burstRate': '100.000000',
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/stormctrlp',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'persistentOnReload': 'true',
                    'rate': '100.000000',
                    'ratePps': '4294967295',
                    'status': '',
                    'type': 'all'
                }
            }
        }, {
            'nfmPhysIf': {
                'attributes': {
                    'asicNum': '0',
                    'dn': 'sys/intf/phys-[eth1/3]/nfmphysif',
                    'sliceNum': '0',
                    'sliceSrcId': '0',
                    'slotNum': '0'
                }
            }
        }, {
            'nwRtPathToIf': {
                'attributes': {
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/rtpathToIf-[sys/conng/path-[eth1/3]]',
                    'modTs': '2018-10-11T20:05:37.522+00:00',
                    'parentSKey': 'eth1/3',
                    'persistentOnReload': 'true',
                    'status': '',
                    'tCl': 'nwPathEp',
                    'tDn': 'sys/conng/path-[eth1/3]',
                    'tSKey': 'eth1/3'
                }
            }
        }, {
            'pcAggrMbrIf': {
                'attributes': {
                    'bdlPortNum': '0',
                    'channelingSt': 'unknown',
                    'childAction': '',
                    'dn': 'sys/intf/phys-[eth1/3]/aggrmbrif',
                    'flags': '',
                    'ltlProgrammed': 'no',
                    'modTs': 'never',
                    'name': '',
                    'operSt': 'down',
                    'persistentOnReload': 'false',
                    'status': '',
                    'summOperSt': 'down',
                    'uptime': '00:00:00:00.000'
                }
            }
        }, {
            'rmonDot3Stats': {
                'attributes': {
                    'alignmentErrors': '0',
                    'babble': '0',
                    'carrierSenseErrors': '0',
                    'clearTs': 'never',
                    'controlInUnknownOpcodes': '0',
                    'deferredTransmissions': '0',
                    'dn': 'sys/intf/phys-[eth1/3]/dbgDot3Stats',
                    'excessiveCollisions': '0',
                    'fCSErrors': '0',
                    'frameTooLongs': '0',
                    'inPauseFrames': '0',
                    'inputdribble': '0',
                    'internalMacReceiveErrors': '0',
                    'internalMacTransmitErrors': '0',
                    'lateCollisions': '0',
                    'lostCarrierErrors': '0',
                    'multipleCollisionFrames': '0',
                    'noCarrierErrors': '0',
                    'outPauseFrames': '0',
                    'runts': '0',
                    'sQETTestErrors': '0',
                    'singleCollisionFrames': '0',
                    'symbolErrors': '0'
                }
            }
        }, {
            'rmonEtherStats': {
                'attributes': {
                    'broadcastPkts': '0',
                    'cRCAlignErrors': '0',
                    'clearTs': 'never',
                    'collisions': '0',
                    'dn': 'sys/intf/phys-[eth1/3]/dbgEtherStats',
                    'dropEvents': '0',
                    'fragments': '0',
                    'giantPkts': '0',
                    'ifdowndrop': '0',
                    'ignored': '0',
                    'jabbers': '0',
                    'multicastPkts': '0',
                    'octets': '0',
                    'overrun': '0',
                    'oversizePkts': '0',
                    'pkts': '0',
                    'pkts1024to1518Octets': '0',
                    'pkts128to255Octets': '0',
                    'pkts1519to1548Octets': '0',
                    'pkts256to511Octets': '0',
                    'pkts512to1023Octets': '0',
                    'pkts64Octets': '0',
                    'pkts65to127Octets': '0',
                    'rXNoErrors': '0',
                    'rxOversizePkts': '0',
                    'rxPkts1024to1518Octets': '0',
                    'rxPkts128to255Octets': '0',
                    'rxPkts1519to1548Octets': '0',
                    'rxPkts256to511Octets': '0',
                    'rxPkts512to1023Octets': '0',
                    'rxPkts64Octets': '0',
                    'rxPkts65to127Octets': '0',
                    'stormSupressedPkts': '0',
                    'tXNoErrors': '0',
                    'txOversizePkts': '0',
                    'txPkts1024to1518Octets': '0',
                    'txPkts128to255Octets': '0',
                    'txPkts1519to1548Octets': '0',
                    'txPkts256to511Octets': '0',
                    'txPkts512to1023Octets': '0',
                    'txPkts64Octets': '0',
                    'txPkts65to127Octets': '0',
                    'underrun': '0',
                    'undersizePkts': '0',
                    'watchdog': '0'
                }
            }
        }, {
            'rmonIfHCIn': {
                'attributes': {
                    'broadcastPkts': '0',
                    'clearTs': 'never',
                    'dn': 'sys/intf/phys-[eth1/3]/dbgIfHCIn',
                    'multicastPkts': '0',
                    'octets': '0',
                    'ucastPkts': '0'
                }
            }
        }, {
            'rmonIfHCOut': {
                'attributes': {
                    'broadcastPckts': '0',
                    'broadcastPkts': '0',
                    'clearTs': 'never',
                    'dn': 'sys/intf/phys-[eth1/3]/dbgIfHCOut',
                    'multicastPkts': '0',
                    'octets': '0',
                    'ucastPkts': '0'
                }
            }
        }, {
            'rmonIfIn': {
                'attributes': {
                    'broadcastPkts': '0',
                    'clearTs': 'never',
                    'discards': '0',
                    'dn': 'sys/intf/phys-[eth1/3]/dbgIfIn',
                    'errors': '0',
                    'multicastPkts': '0',
                    'nUcastPkts': '0',
                    'noBuffer': '0',
                    'octetRate': '0',
                    'octets': '0',
                    'packetRate': '0',
                    'rateInterval': '300',
                    'ucastPkts': '0',
                    'unknownEtype': '0',
                    'unknownProtos': '0'
                }
            }
        }, {
            'rmonIfOut': {
                'attributes': {
                    'broadcastPkts': '0',
                    'clearTs': 'never',
                    'discards': '0',
                    'dn': 'sys/intf/phys-[eth1/3]/dbgIfOut',
                    'errors': '0',
                    'multicastPkts': '0',
                    'nUcastPkts': '0',
                    'octetRate': '0',
                    'octets': '0',
                    'packetRate': '0',
                    'qLen': '0',
                    'rateInterval': '300',
                    'ucastPkts': '0'
                }
            }
        }, {
            'l1PhysIf': {
                'attributes': {
                    'FECMode': 'auto',
                    'accessVlan': 'vlan-1',
                    'adminSt': 'up',
                    'autoNeg': 'on',
                    'beacon': 'off',
                    'bw': 'default',
                    'childAction': '',
                    'controllerId': '',
                    'delay': '1',
                    'descr': '',
                    'dn': 'sys/intf/phys-[eth1/3]',
                    'dot1qEtherType': '0x8100',
                    'duplex': 'auto',
                    'ethpmCfgFailedBmp': '',
                    'ethpmCfgFailedTs': '00:00:00:00.000',
                    'ethpmCfgState': '0',
                    'id': 'eth1/3',
                    'inhBw': '4294967295',
                    'layer': 'Layer2',
                    'linkDebounce': '100',
                    'linkDebounceLinkUp': '0',
                    'linkLog': 'default',
                    'linkTransmitReset': 'enable',
                    'mdix': 'auto',
                    'medium': 'broadcast',
                    'modTs': '2018-10-18T23:43:52.312+00:00',
                    'mode': 'access',
                    'mtu': '1500',
                    'name': '',
                    'nativeVlan': 'vlan-1',
                    'packetTimestampEgressSourceId': '0',
                    'packetTimestampIngressSourceId': '0',
                    'packetTimestampState': 'disable',
                    'persistentOnReload': 'true',
                    'portT': 'leaf',
                    'routerMac': 'not-applicable',
                    'snmpTrapSt': 'enable',
                    'spanMode': 'not-a-span-dest',
                    'speed': 'auto',
                    'speedGroup': 'auto',
                    'status': '',
                    'switchingSt': 'disabled',
                    'trunkLog': 'default',
                    'trunkVlans': '1-4094',
                    'usage': 'discovery',
                    'userCfgdFlags': 'admin_layer,admin_state',
                    'vlanmgrCfgFailedBmp': '',
                    'vlanmgrCfgFailedTs': '00:00:00:00.000',
                    'vlanmgrCfgState': '0',
                    'voicePortCos': 'none',
                    'voicePortTrust': 'disable',
                    'voiceVlanId': 'none',
                    'voiceVlanType': 'none'
                }
            }
        }
    ]
}

To create a subscription to a query, perform the query with the option ?subscription=yes. This example creates a subscription to a query of the Layer 1 physical ethernet interface in the JSON format:

GET https://<IP_Address>/api/mo/sys/intf/phys-[eth1/3].json?subscription=yes&query-target=subtree

The query response contains a subscription identifier, subscriptionId, that you can use to refresh the subscription and to identify future notifications from this subscription.

Creating a Subscription With Filters

Creating a Subscription With Filters
GET https://<IP_Address>/api/mo/sys/intf/phys-[eth1/3].json?subscription=yes&query-target=subtree&query-target-filter=and(updated(ethpmPhysIf.adminSt),eq(ethpmPhysIf.adminSt,"down"))
{
    'totalCount': '0',
    'subscriptionId': '18374686496834715649',
    'imdata': []
}

To create a subscription to a filtered query, perform the query with the option ?subscription=yes. This example creates a subscription to a query of the Layer 1 physical ethernet interface and is filtered to retrieve the admin state in the JSON format for the ethpmPhysIf MO:

GET https://<IP_Address>/api/mo/sys/intf/phys-[eth1/3].json?subscription=yes&query-target=subtree&query-target-filter=and(updated(ethpmPhysIf.adminSt),eq(ethpmPhysIf.adminSt,"down"))

The query response contains a subscription identifier and subscriptionId that you can use to refresh the subscription and to identify future notifications from this subscription.

Receiving Notifications

Receiving Notifications
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 28 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "l1PhysIf": {
                "attributes": {
                    "adminSt": "down",
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]",
                    "modTs": "2018-10-18T23:45:52.078+00:00",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 28 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "lastLinkStChg": "2018-10-18T23:45:52.083+00:00",
                    "operBitset": "3-4,7,13",
                    "operSt": "link-up",
                    "operStQual": "admin-config-change",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 28 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "lastLinkStChg": "2018-10-18T23:45:52.241+00:00",
                    "operBitset": "4,7,13,35",
                    "operSt": "down",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 29 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "operBitset": "7,13,35",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 29 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "adminSt": "down",
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 29 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "operBitset": "13,35",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 29 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "operStQual": "admin-down",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 41 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "l1PhysIf": {
                "attributes": {
                    "adminSt": "up",
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]",
                    "modTs": "2018-10-18T23:46:04.995+00:00",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 41 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "operBitset": "7,13,35",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 42 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "adminSt": "up",
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 42 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "operBitset": "13,35",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 42 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "operBitset": "4,13,35",
                    "operDuplex": "auto",
                    "operFECMode": "auto",
                    "operSpeed": "auto",
                    "operStQual": "link-failure",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree received @ 22 : 38: 45 UTC---------- - {
    "subscriptionId": ["18374686492539748353"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "lastLinkStChg": "2018-10-18T23:46:08.577+00:00",
                    "operBitset": "3-4,13",
                    "operSt": "up",
                    "operStQual": "none",
                    "resetCtr": "3",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}

An event notification from the subscription delivers a data structure that contains the subscription ID and the MO description.

Because multiple active subscriptions can exist for a query, a notification can contain multiple subscription IDs.

Receiving Notifications to Filtered Subscriptions

Receiving Notifications to Filtered Subscriptions
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree & query - target - filter = and(updated(ethpmPhysIf.adminSt), eq(ethpmPhysIf.adminSt, "down"))received @ 22 : 40: 34 UTC---------- - {
    "subscriptionId": ["18374686496834715649"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "adminSt": "down",
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}
---------- - sys / intf / phys - [eth1 / 3].json ? subscription = yes & query - target = subtree & query - target - filter = and(updated(ethpmPhysIf.adminSt), eq(ethpmPhysIf.adminSt, "down"))received @ 22 : 41: 07 UTC---------- - {
    "subscriptionId": ["18374686496834715649"],
    "imdata": [{
            "ethpmPhysIf": {
                "attributes": {
                    "adminSt": "down",
                    "childAction": "",
                    "dn": "sys/intf/phys-[eth1/3]/phys",
                    "rn": "",
                    "status": "modified"
                }
            }
        }
    ]
}

An event notification from the subscription delivers a data structure that contains the subscription ID and the MO description.

Because multiple active subscriptions can exist for a query, a notification can contain multiple subscription IDs.

Refreshing the Subscription

To continue to receive event notifications, you must periodically refresh each subscription during your API session. To refresh a subscription, send an HTTP GET message to the API method subscriptionRefresh with the parameter id equal to the subscriptionId as in this example:

GET https://<IP_Address>/api/subscriptionRefresh.json?id=72057611234574337

The API returns an empty response to the refresh message unless the subscription has expired.

Deleting the Subscription

Deleting the Subscription
```[DME]
POST http://mgmt0/api/subscriptionDelete.json?id=18374686505424650242

After you delete the subscription, you stop receiving notifications for that subscription.

Faults

In NX-API-REST, a fault is represented as a mutable, stateful, and persistent MO. When a specific condition occurs, such as a component failure, configuration deployment failure or an alarm, the system creates a fault MO as a child object to the MO that is primarily associated with the fault. For a fault object class, the fault conditions are defined by the fault rules of the parent object class.
In most cases, a fault MO is automatically created, escalated, DE-escalated, and deleted by the system as specific conditions are detected.

If the same condition is detected multiple times while the corresponding fault MO is active, no additional instances of the fault MO are created. A fault MO remains in the system until the fault condition is cleared. The fault MO is deleted according to the settings in the fault collection and fault retention policies. A fault MO is read-only unless it is in the cleared and retained state, when it can be deleted by the user by acknowledging it.

The creation of a fault MO can be triggered by internal processes such as finite state machine (FSM) transitions or detected component failures, or by conditions specified by various fault policies, some of which are user configurable. For example, user can set fault thresholds on statistical measurements such as data traffic, temperatures etc.

Fault Objects, Records, and Log

Fault Objects

A fault object is represented by the following:

  • fault:Inst — When a fault occurs in an MO, a fault instance MO is created under the MO that experienced the fault condition.

Fault Records

For every fault, a fault record object (fault:Record) is created in the fault log. A fault record is an immutable object that records a state transition for a fault instance object. Record creation is triggered by fault instance MO creation or deletion or by modification of key properties (for example, severity, life cycle, or acknowledgment) of the fault instance object.

Although a fault instance object is mutable, the fault record object is not. All properties of the record are set at the time the record object is created.
A record object contains a complete snapshot of the fault instance object and is logically organized as a flat list under a single container. The record object contains properties from the corresponding instance object (fault:Inst) such as severity (original, highest, and previous), acknowledgment, occurrence, and life cycle as well as inherited properties that provide a snapshot of the fault instance and the nature and time of its change. The record is meant to be queried using time-based filters or property filters for severity, affected DN, or other criteria.

When a fault record object is created, it is added to the fault log. The object creation can also trigger the export of record details to an external destination by syslog, SNMP trap, or other methods.

Fault Log

The fault log collects and retains fault records. Records are purged only when the maximum capacity of the log is reached and space is needed for new fault records. Depending on the log space availability, a fault record can be retained in the fault log long after the fault object itself has been deleted.

Fault Severity

A fault raised by the system can transition through more than one severity during its life cycle. This table describes the possible fault severities in decreasing order of severity:

Severity Description
critical A service-affecting condition that requires immediate corrective action. For example, this severity could indicate that the managed object is out of service and its capability must be restored.
major A service-affecting condition that requires urgent corrective action. For example, this severity could indicate a severe degradation in the capability of the managed object and that its full capability must be restored.
minor A nonservice-affecting fault condition that requires corrective action to prevent a more serious fault from occurring. For example, this severity could indicate that the detected alarm condition is not currently degrading the capacity of the managed object.
warning A potential or impending service-affecting fault that currently has no significant effects in the system. An action should be taken to further diagnose, if necessary, and correct the problem to prevent it from becoming a more serious service-affecting fault.
info A basic notification or informational message that is possibly independently insignificant. (Used only for events)
cleared A notification that the condition that caused the fault has been resolved, and the fault has been cleared.

Fault Types

A fault raised by the system can be one of the types described in this table:

Type Description
Generic The system has detected a generic issue.
equipment The system has detected that a physical component is inoperable or has another functional issue.
configuration The system is unable to successfully configure a component.
connectivity The system has detected a connectivity issue, such as an unreachable adapter.
environmental The system has detected a power issue, thermal issue, voltage issue, or a loss of CMOS settings.
management The system has detected a serious management issue, such as one of the following: Critical services could not be started. Components in the instance include incompatible firmware versions.
Network The system has detected a network issue, such as a link down.
operational The system has detected an operational issue, such as a log capacity limit or a failed component discovery.

Fault Properties

The system provides detailed information about each fault raised. This table describes the fault properties:

Property Description
code The fault code (for example, F1017).
rule id The identifier of the rule that generated the fault instance.
Id The unique identifier assigned to the fault.
Cause The probable cause category (for example, equipment-inoperable).
Type The type of fault (for example: connectivity or environmental).
Severity The current severity level of the fault.
Created The day and time when the fault occurred.
lastTransition The day and time on which the severity or life cycle state for the fault last changed.
Descry The description of the fault.
Lc The life cycle state of the fault (for example, soaking).
Occur The number of times the event that raised the fault occurred.
origSeverity The severity assigned to the fault on the first time that it occurred.
prevSeverity If the severity has changed, this is the previous severity.
highestSeverity The highest severity encountered for this issue.

Viewing Faults Using the API

One can view faults using the API query methods to search for fault MOs, which can be of class fault:Inst . One can search for all instances or one can refine one’s search using query filters.

Faults and Retries

When you provision or configure a device using Netconf, Restconf, DME, or gRPC, you will receive a success message when the payload is accepted by the Device. The changes are then committed to the database and a notification is sent to all the backend applications; this may take some time to converge to the final state. During this time, copy run start will fail if the retry is in progress. To check for the retires, enter the show nxapi retries CLI command. If the retries are not successful, then a fault is raised by the backend applications, which you should monitor/register for the same. To clear the retries, enter the clear nxapi retries CLI command. Then, you can run copy run start successfully.

Events

Any configuration or state change in any MO is considered an event. Most events are part of the normal workflow and there is no need to record their occurrence or to bring them to the attention of the user unless they meet one of the following criteria:

  • The event is defined in the model as requiring notification.
  • The event follows a user action that is required to be auditable.

A loggable event is represented by an event record object, which is an immutable, stateless, and persistent MO created by the system to record the occurrence of a specific set of conditions at a given point in time.

Although an event record MO is usually triggered by conditions in another MO, it is not contained by that MO but is contained in an event log.

NX-API-REST event MOs are stateless. An event MO created by the NX-API-REST is never modified or cleared. An event MO is deleted by the rotation of the event log as newer events are added and log space is needed.