Config Validation API

Cisco IOS XR Python API for use by Config Scripts to validate / modify configuration.

Exceptions:

Error

Base exception type for this module.

UnexpectedError

Error thrown when an unexpected API failure occurs.

PathNotFound

Error thrown when a provided path does not correspond to a schema node in the loaded config.

InvalidNodeKind

Error thrown when the type of node specified was not valid for the action that was attempted.

ExpiredNode

Error thrown when a DataNode object or list object has expired or is otherwise invalid.

InvalidArg

Error thrown when an argument to one of the APIs is invalid, by type or in the context of the API.

BadDatatype

Error thrown when passing a value to one of the APIs is the wrong datatype.

InvalidPath

Error thrown when a provided path is malformed, or otherwise invalid.

ErrListKey

Error thrown when an attempt to directly modify a list key is made.

ErrVirtLeaf

Error thrown when an attempt to directly modify a virtual leaf node, i.e. a node that is not part of the XR configuration schema.

InvalidAPICall

Error thrown when an API is incorrectly used.

Functions:

register_validate_callback

Register a callback function on a path (or list of paths).

add_error

Add a validation failure with error level to the given config items.

add_warning

Add a validation failure at warning level to the given config items.

Classes:

DataNode

Object representing data in the database, corresponding to a schema node and its instance.

RootDataNode

Subclass of DataNode which corresponds to the root schema node.

exception config_validation.Error

Bases: Exception

Base exception type for this module.

__str__()

Error message detailing why this exception was raised.

exception config_validation.UnexpectedError(errno, err_msg)

Bases: Error

Error thrown when an unexpected API failure occurs. This should not be caught, and should be allowed to terminate the script.

exception config_validation.PathNotFound(path)

Bases: Error

Error thrown when a provided path does not correspond to a schema node in the loaded config.

path

Path which was not found in the loaded config, relative to any DataNode being used.

If multiple paths were provided and could be wrong, the first provided path is given here.

exception config_validation.InvalidNodeKind(node_path)

Bases: Error

Error thrown when the type of node specified was not valid for the action that was attempted.

node_path

Absolute path of the node which cannot be used for this operation.

exception config_validation.ExpiredNode

Bases: Error

Error thrown when a DataNode object or list object has expired or is otherwise invalid.

exception config_validation.InvalidArg(arg)

Bases: Error

Error thrown when an argument to one of the APIs is invalid, by type or in the context of the API.

arg

Argument which was provided and may be invalid.

exception config_validation.BadDatatype(node_path, arg)

Bases: Error

Error thrown when passing a value to one of the APIs is the wrong datatype.

node_path

Absolute path the operation was on, for context.

arg

Argument which was provided and is the wrong datatype.

exception config_validation.InvalidPath(path)

Bases: Error

Error thrown when a provided path is malformed, or otherwise invalid.

path

Path which was invalid.

exception config_validation.ErrListKey(node_path)

Bases: Error

Error thrown when an attempt to directly modify a list key is made.

node_path

Absolute path of the list key node which was incorrectly accessed.

exception config_validation.ErrVirtLeaf(node_path)

Bases: Error

Error thrown when an attempt to directly modify a virtual leaf node, i.e. a node that is not part of the XR configuration schema.

node_path

Absolute path of the virtual leaf node which was incorrectly accessed.

exception config_validation.InvalidAPICall(api_name, reason)

Bases: Error

Error thrown when an API is incorrectly used.

api_name

Name of the API that was called.

config_validation.register_validate_callback(path_strs, cb_fn)

Register a callback function on a path (or list of paths).

The callback function will be invoked whenever a commit is made which impacts the paths to config provided. The different path node types are handled as follows:

  • Leaf: Called if the leaf is created, deleted or modified.

  • Presence Container: Called if the container is created or deleted.

  • Non-presence Container: Called on the transitions between empty and non-empty.

  • List/leaf-list: Called if a list entry is created or deleted.

If a path to a container or list node ends in a wildcard ‘*’, the callback will be called if any node under the given path is created, deleted or modified.

  • E.g. '/path/to/list/*'.

Registrations on the root node (“/”) or on everything beneath the root node (“/*”) are not supported.

The callback function must have the following signature, accepting a single positional argument “root” which will be provided by the infra upon calling as a RootDataNode object representing the root node:

def cb_fn(root):
    "My validation callback."
    pass
Parameters:
  • path_strs

    Schema YPath (or list of schema paths) to register on, specified from the root.

    • E.g. '/container1/container2/list1/leaf1'.

    • E.g. ['/container1/container2/*', '/container1/leafA'].

    Each YPath string must be an absolute path and must not be the root node “/” or everything under the root node “/*”.

  • cb_fn – Function to be called when the registered paths are impacted by a commit. The name must be able to be encoded using ASCII.

Raises:
  • InvalidArg – If cb_fn is not a callable with the signature described above, or if any provided path: - Is not a non-empty string - Is a relative path - Is the root node “/” - Is a wildcard root “/*”.

  • PathNotFound – If any of the supplied paths do not map to schema nodes.

config_validation.add_error(data_nodes, msg)

Add a validation failure with error level to the given config items.

Parameters:
  • data_nodes

    DataNode object or string path to data node (or list of) to add the validation failure to.

    The root node or a path of “/” are invalid arguments - all failures must be raised on specific items.

  • msg – String detailing the validation failure. Must be able to encode using ASCII.

Raises:
  • InvalidArg – If the root node, an empty path, a path of “/”, an otherwise invalid path, or an object other than a DataNode or string are provided.

  • PathNotFound – If one or more paths provided cannot be mapped to a schema node in the loaded config.

config_validation.add_warning(data_nodes, msg)

Add a validation failure at warning level to the given config items.

Parameters:
  • data_nodes

    DataNode object or string path to data node (or list of) to add the validation failure to.

    The root node or a path of “/” are invalid arguments - all failures must be raised on specific items.

  • msg – String detailing the validation failure. Must be able to encode using ASCII.

Raises:
  • InvalidArg – If the root node, an empty path, a path of “/”, an otherwise invalid path, or an object other than a DataNode or string are provided.

  • PathNotFound – If one or more paths provided cannot be mapped to a schema node in the loaded config.

class config_validation.DataNode(yve_node=None)

Bases: object

Object representing data in the database, corresponding to a schema node and its instance.

A special instance of this class is provided to represent the “root” node.

path

Path to this node from the root, e.g. "/path/to/node".

value

Current value of the associated config. This reflects changes from the user’s config buffer.

This value depends on the type of node represented by this data node:

  • Leaf and leaf-list entries: The value of the config item.

  • Presence container: True if presence is set, False otherwise.

  • Non-presence container and list entries: Always None.

empty

Whether the current node is empty or not. The return depends on the type of node represented by this data node:

  • Leaf of leaf-list entries: Always None.

  • Containers and list entries: Boolean value indicating if any config is set in the container.

parent_node

DataNode object representing the parent of this node.

The node is not valid when a change to the CCV datastore is confirmed, i.e. following the end of a check or batch operation. Any use of the same DataNode object (such as one saved between calls to the callback) after this will raise ExpiredNode.

Any use of an object which is directly initialized will raise ExpiredNode. This object should be initialized using get_node().

All methods and property access may raise UnexpectedError if an unexpected error occurs whilst calling an internal API.

Attributes:

value

Retrieve the current value of this node.

parent_node

Retrieve the parent of this node as a DataNode instance.

path

Retrieve the YPath representation of the node path as a string.

empty

Retrieve whether this node is "empty" or not.

Methods:

get_node

Get another DataNode for data relative to this node.

get_list

Get an object representing a list relative to this node.

set_node

Set the value of a config node as part of the changes to be suggested by the current script callback.

set

Identical to set_node(), except that path_str is given as None to indicate that it is the current node (self) which should be set.

delete_node

Delete a config node as part of the changes to be suggested by the current script callback.

delete

Identical to delete_node(), except that path_str is given as None to indicate that it is the current node (self) which should be deleted.

property value

Retrieve the current value of this node.

This value depends on the type of node represented by this data node:

  • Leaf and leaf-list entries: The value of the config item.

  • Presence containers and list entries: True if node has presence set, False otherwise.

  • Non-presence containers: Always None.

property parent_node

Retrieve the parent of this node as a DataNode instance.

property path

Retrieve the YPath representation of the node path as a string.

property empty

Retrieve whether this node is “empty” or not.

get_node(path_str)

Get another DataNode for data relative to this node.

Parameters:

path_str – Relative YPath string to the data to get. All keys must be specified for all list and leaf-list identifiers in the path.

Returns:

Object representing the relative data if it is set, else None.

Return type:

DataNode

Raises:
  • InvalidArg – If the argument is not a non-empty string or if the argument is “/”.

  • PathNotFound – If the path does not map to a schema data node.

  • InvalidNodeKind – If the path does not correspond to a node which can be represented as a DataNode, e.g. a list rather than a specific entry of the list.

get_list(path_str)

Get an object representing a list relative to this node.

Parameters:

path_str – Relative YPath string to the list to get. All keys must be specified for all list and leaf-list identifiers in the path except for the last, which should identify the list to get.

Returns:

An object which behaves as a standard Python list, always iterable and countable. If the list instance has no entries or any parent does not exist, the count will be 0 and the iterator over the list will be empty.

Unlike a standard list, this object is a dynamic view on the config: the count and the iterator will represent the current state of the list (even if the list changes from not existing to having entries or vice versa).

Adding entries will increment the count, and the entry will appear in the iterator. List entries should not be added, modified or deleted during an iteration (like elements in a standard list should not be deleted etc. during iteration).

The order of list entries in the list (during an iteration) is not guaranteed unless the item is marked as ordered-by user in the schema. Then, order of entries returned will be the configured order.

Raises:
  • InvalidArg – If the argument is not a non-empty string or if the argument is “/”.

  • PathNotFound – If the path does not map to a schema node.

  • InvalidNodeKind – If the path does not correspond to a list node, e.g. if it is a list entry.

set_node(path_str, value=None)

Set the value of a config node as part of the changes to be suggested by the current script callback. Returns the (new) node as a DataNode.

The behavior depends on the type of node represented by the given path:
  • Leaf: The value of the config item is set or the item is created with that value if it does not exist.

  • Presence containers: Creates the container. Value should be given as None.

  • List entries: Creates the list entry if it does not already exist. List entries created this way persist even if no config is set under them. Value should be given as None.

  • Non-presence containers: Raises InvalidNodeKind, as this operation is invalid. This is also the case if this node is a non-presence container, and this API is called with path_str as None, i.e. on itself.

To set a leaf-list entry, the entry should be set analogously to a normal list entry, but providing the keyed path of the list and providing None as the value, e.g. creating entry ‘foo’:

root.set_node("/path/to/string-leaf-list['foo']")
Parameters:
  • path_str – Relative YPath string to the data node to set. If given as None, the node to set is taken to be this node (self).

  • value – Value to set the node to. Should only be provided if setting a leaf. If provided, must be of type int, str or bool depending on the leaf type. Leaves of any type which is not empty may be set using the type str. For presence containers and (leaf-)list entries, it is ignored, so the default None should be used.

Returns:

Object representing the set data.

Cannot be None unless this function raises an error, as the node would be created by this operation.

Return type:

DataNode

Raises:
  • InvalidArg – If path_str is not a non-empty string (or None) or if it is “/”, or if value is not of the correct type for the node given.

  • PathNotFound – If the path does not map to a schema node.

  • InvalidNodeKind – If attempting to set a non-presence container or the root node (not supported), or the path does not point to config which corresponds to a DataNode (such as a list definition).

set(value=None)

Identical to set_node(), except that path_str is given as None to indicate that it is the current node (self) which should be set.

delete_node(path_str)

Delete a config node as part of the changes to be suggested by the current script callback.

Deleting something which is not currently set does nothing.

The behavior depends on the type of node represented by the given path:
  • Leaf and leaf-list entries: The item is deleted.

  • List entries/containers: Everything under it is (recursively) deleted. For list entries, the entry is deleted. For presence containers, the presence is cleared.

  • List definitions: All entries of the list are deleted.

Parameters:

path_str – Relative YPath string to the node to delete. If given as None, the node to delete is taken to be this node (self).

Raises:
  • InvalidArg – If path_str is not a non-empty string (or None) or if it is “/”.

  • PathNotFound – If the path does not map to a schema node.

  • InvalidNodeKind – If attempting to delete the root node (not supported).

delete()

Identical to delete_node(), except that path_str is given as None to indicate that it is the current node (self) which should be deleted.

class config_validation.RootDataNode(yve_node=None)

Bases: DataNode

Subclass of DataNode which corresponds to the root schema node.

Registered callbacks will be given an object which is an instance of this class, from which any other node in the schema may be accessed.

This has the same attributes as a DataNode.

This inherits the same methods as a DataNode with the exception of:

The above methods will raise InvalidNodeKind if called.

All methods and property access may raise UnexpectedError if an unexpected error occurs whilst calling an internal API.

Attributes:

value

Retrieve the value of the root node.

parent_node

Retrieve the parent data node of the root node.

path

Retrieve the YPath representation of the root node as a string.

Methods:

get_interface

Get a DataNode representing the current configuration for an interface if any such configuration exists.

set_interface

Set an interface entry, creating it if one doesn't exist.

delete_interface

Delete an interface entry.

get_hw_location

Get a DataNode representing the current configuration for a hardware location if any such configuration exists.

set_hw_location

Set an entry for a hardware location, creating it if one doesn't exist.

delete_hw_location

Delete an entry for a hardware location.

property value

Retrieve the value of the root node. This is always None.

property parent_node

Retrieve the parent data node of the root node. This is always None.

property path

Retrieve the YPath representation of the root node as a string.

get_interface(name)

Get a DataNode representing the current configuration for an interface if any such configuration exists.

This checks for both active and pre-config versions (it is guaranteed that no interface has both).

This should be used with the native model-family in preference to the generic get_node() API as it allows scripts to ignore the distinction between pre-configuration and active configuration.

This helper is deprecated for use with the UM model-family.

Parameters:

name – The name of the interface to get.

Returns:

Object representing the interface if it is set, else None.

Return type:

DataNode

Raises:
set_interface(name)

Set an interface entry, creating it if one doesn’t exist.

If an interface with this name is already configured in active config or pre-config then this is a no-op and the existing interface’s DataNode is returned.

This should be used with the native model-family in preference to the generic set_node() API as it allows scripts to ignore the distinction between pre-configuration and active configuration.

This helper is deprecated for use with the UM model-family.

Parameters:

name – The name of the interface to set.

Returns:

Object representing the set interface.

Return type:

DataNode

Raises:
delete_interface(name)

Delete an interface entry.

If an interface with this name is currently active, or is in preconfiguration, the entry and all items under the interface entry will be recursively deleted.

Deleting an interface which is not currently set does nothing.

This should be used with the native model-family in preference to the generic delete_node() API as it allows scripts to ignore the distinction between pre-configuration and active configuration.

This helper is deprecated for use with the UM model-family.

Parameters:

name – The name of the interface to delete configuration for.

Raises:
get_hw_location(name)

Get a DataNode representing the current configuration for a hardware location if any such configuration exists.

This checks for both active and pre-config versions (it is guaranteed that no hardware location has both).

This should be used with the native model-family in preference to the generic get_node() API as it allows scripts to ignore the distinction between pre-configuration and active configuration.

This helper is deprecated for use with the UM model-family.

Parameters:

name – The name of the hardware location to get configuration for.

Returns:

Object representing the hardware location if it is set, else None.

Return type:

DataNode

Raises:
set_hw_location(name)

Set an entry for a hardware location, creating it if one doesn’t exist.

If a hardware location with this name is already configured in active config or pre-config then this is a no-op and the existing DataNode is returned.

This should be used with the native model-family in preference to the generic set_node() API as it allows scripts to ignore the distinction between pre-configuration and active configuration.

This helper is deprecated for use with the UM model-family.

Parameters:

name – The name of the hardware location to set configuration for.

Returns:

Object representing the set hardware location.

Return type:

DataNode

Raises:
delete_hw_location(name)

Delete an entry for a hardware location.

If a hardware location with this name is currently in active configuration or pre-configuration, the entry and all items under it will be recursively deleted.

Deleting the configuration for a hardware location which is not currently set does nothing.

This should be used with the native model-family in preference to the generic delete_node() API as it allows scripts to ignore the distinction between pre-configuration and active configuration.

This helper is deprecated for use with the UM model-family.

Parameters:

name – The name of the hardware location to delete configuration for.

Raises:

YPath Specification

This section documents what is meant by specifying a “YPath” in the Config Validation API, and what format the path should take in different circumstances.

The “YPath” format is based on an “XPath”, made specific to Yang in some ways, and is used to specify a given schema item or data item within the context of the API.

A YPath is comprised of one or more path segments, separated by a forward slash /. The path is either absolute if it starts with / (indicates a full path from the root), or relative, in which case it starts with the first path segment.

Each path segment contains the node identifier, in the format:

<module-name>:<node-name>

The <module-name>: is optional if the module for this node is the same as for the previous path segment. If the path is absolute, the first segment must specify the module, else the path is invalid. If the path is relative, then if the first segment omits the module name, it will be assumed to be the same as the module of the node it is applied relative to.

Schema Paths

A schema path is a YPath which points to an item in the schema, but does not given an exact instance of it (so is referring to all instances of it). This is used when specifying parts of the schema to register a callback on, for example. A schema path is made up of path segments which are just node identifiers, as described previously.

A schema path for an example schema may look like:

/module-1:container/path/with/module-2:list/leaf

Data Paths

A data path is a YPath which fully specifies a piece of data, pointing to a specific instance of a schema item. For a data path, all list keys must be specified, usually for all list (and leaf-list) identifiers in the path. The keys for the final list (or leaf-list) identifier can be omitted if, for example, getting a list object, as a specific list entry or leaf-list item is not needed. All list identifiers in the path must have keys when getting a data node handle, which points to the exact instance of the data.

For (leaf-)list identifiers, the keys specifying the exact entry or item can be given, in the following format (using square brackets and a comma-separated list of keys):

<module-name>:<node-name>[<key-name-1>=<value-1>, <key-name-2>=<value-2>, ...]

The number of keys given must match the number of key leaves for a (leaf-)list identifier. Giving the key names using <key-name-N>= is optional (and only applies to list identifiers), as all keys must be specified in the correct order even if names are provided. This order matches the “keys” statement in the Yang list definition, or the leaf order in the Yang leaf-list definition. If any keys are provided, all keys must be provided.

Key values can always be specified as a string enclosed in single or double quotes, e.g. "my-key-val". However, if the type for the key leaf is numeric (uint64, int64, etc.), unquoted numeric literals can be used or if the leaf type is boolean, unquoted boolean literals ‘true’ or ‘false’ may be used.

A data path for an example schema may look like:

/module-1:listA[instance=1]/path/with/module-2:listB[key-1="foo", key-2=89]/leaf