Using Junos PyEZ Configuration Tables to Configure Structured Resources on Devices Running Junos OS

 

Junos PyEZ configuration Tables and Views that specify the set property enable you to define structured resources that can be used to programmatically configure devices running Junos OS. After loading or importing the Table definition for your structured resource into your Junos PyEZ application, the application can configure the resource on your devices. This topic discusses the general process and some specific tasks for using Junos PyEZ configuration Tables and Views to configure structured resources on a device.

General Configuration Process

The configuration Table set property identifies the configuration hierarchy level at which a resource is configured and sets the XPath context for fields in the View. For example, the following Table defines a user resource at the [edit system login] hierarchy level:

The fields that are included in the View define which leaf statements the user can configure for that resource. A field can define a default value as well as type and constraint checks.

To configure a structured resource on a device, you must load or import the Table into your application. You then create a Table object and associate it with the Device object representing the target device. For example:

To define values for a resource’s configuration statements, set the corresponding field names as defined in the View equal to the desired values.

The default value for a field is None unless the View explicitly defines a default for that field. If the View defines a type or constraint check for a field, the application must supply the correct data type and value for that field and ideally handle any errors that might be raised in the event that the check fails. You must always define values for any key fields that are declared in the Table’s key-field property, which in this example is username.

The following code imports UserConfigTable and configures values for the username, userclass, and password fields. The crypt module calculates the hash of the user’s password for the configuration. This example requires Python3 to use the crypt() function with a single argument.

For detailed information about more specific configuration tasks, such as configuring statements with fixed-form keywords or multiple values, configuring multiple instances of a statement or resource, deleting a leaf or container statement, or configuring an object property that corresponds to a Junos XML attribute, see the following sections:

After you configure an object, you must call the append() method to build the corresponding Junos XML configuration and add it to the lxml object that stores the master set of configuration changes for that Table object. The configuration changes only include those fields that have either a default value defined in the View or a user-configured value. Fields that retain their initial value of None are ignored.

After building the XML, the append() method also resets all fields to the their default values or to None if the View does not define a default for that field. This enables you to configure multiple objects in the same application and ensures that you do not unintentionally use a value defined for one resource when you configure subsequent resources. Each time you configure a new resource, you must call append() to add the configuration changes to the master set of changes. For more information about the append() method, see Using append() to Generate the Junos XML Configuration Data.

If necessary, you can also manually reset all fields for a Table object by calling the reset() method.

The reset() method restores all fields back to their default values or to None if the View does not define a default. The reset() method only resets the current values of the fields. It does not affect the XML containing the configuration changes that has been constructed up to that point by calls to the append() method.

You can retrieve the XML configuration representing your changes at any point in the application by calling the get_table_xml() method, which is discussed in detail in Viewing Your Configuration Changes.

After configuring all necessary objects and calling append(), you can load your configuration changes into the shared configuration database on the device by using one of two methods:

  • Call the set() method, which automatically calls the lock(), load(), commit(), and unlock() methods

  • Call the lock(), load(), commit(), and unlock() methods individually

Note

When you create the Table instance with a context manager (with ... as syntax) that includes the mode parameter to use a specific configuration mode, the context manager handles opening and locking and closing and unlocking the database. In this case, you only need to call the load() and commit() methods to configure the device. Calling the lock() or set() method results in a LockError exception.

Using the single set() method provides simplicity, but calling the individual methods provides additional flexibility such as when you need to call other methods after loading the configuration data, but before committing it. For example, you might want to call the diff() or pdiff() methods to review the configuration differences after you load the data but before you commit it. Or you might need to call the rollback() method to reset the candidate configuration back to the active configuration instead of committing it. For more information about the using the different methods to load and commit the configuration data, see Using Junos PyEZ to Configure Devices Running Junos OS and Using Junos PyEZ to Commit the Configuration.

In the case of large load and commit operations that might time out, you can adjust the RPC timeout interval by including the timeout parameter in the set() or commit() method argument list. For more information, see Controlling the RPC Timeout Interval.

A configuration table that specifies the set parameter is a superset and has all the features of a configuration table that specifies the get parameter. You can retrieve configuration data in the same way in your Junos PyEZ application whether the Table specifies set or get. For information about using configuration Tables to retrieve configuration data, see Using Junos PyEZ Configuration Tables to Retrieve Configuration Data.

Configuring Statements Consisting of a Fixed-Form Keyword

A leaf statement is a CLI configuration statement that does not contain any other statements. Most leaf statements define a value for one characteristic of a configuration object and have the following form:

Some leaf statements consist of a fixed-form keyword only, without an associated variable-form value. For example, the ftp statement at the [edit system services] hierarchy level is an example of a fixed-form keyword.

The Junos XML API represents such statements with an empty tag.

To configure a fixed-form keyword in your Junos PyEZ application, such as the ftp statement under [edit system services], set the value of the corresponding field name as defined in the View equal to the Boolean value True.

Consider the following View, which defines the ftp field with a type constraint to ensure that the value for the field is a Boolean:

To configure the ftp field in your Junos PyEZ application, set the field equal to True.

Configuring Multiple Values for the Same Statement

Some Junos OS leaf statements accept multiple values, which might be either user-defined or drawn from a set of predefined values. CLI notation uses square brackets to enclose all values in a single statement, as in the following:

For example, you might need to configure a VLAN ID list for a trunk interface, as in the following configuration:

To configure a leaf statement with multiple values in your Junos PyEZ application, set the value of the corresponding field, as defined in the View, equal to a Python list containing the desired values. In the following example, the vlan_list field maps to the vlan-id-list statement in the CLI. To configure the statement with multiple VLAN IDs, set the field name equal to the list of IDs.

Note

The Python list that you use for the value of a field in your Junos PyEZ application is a comma-delimited list of values. This is different from the space-delimited list that you would configure in the CLI.

Configuring Multiple Instances of the Same Statement

In certain situations, the Junos OS configuration enables you to configure multiple instances of the same statement. For example, you might configure multiple addresses under the same protocol family for a logical interface. In the following configuration snippet, the loopback interface has multiple addresses configured at the [edit interfaces lo0 unit 0 family inet] hierarchy level:

The Junos XML representation of the configuration is as follows:

When you use Junos PyEZ configuration Tables to manage structured resources on devices running Junos OS, you define values for configuration statements by setting the corresponding field names equal to the desired values. However, you cannot define the same field twice in your Junos PyEZ application, because the second value will overwrite the first value. Instead, you must set the field equal to a list of values, and Junos PyEZ handles the conversion to XML.

Consider the following Table and View:

The following sample code illustrates how to configure multiple addresses for the loopback interface in a Junos PyEZ application. In this case, you set the ip_address field equal to a list of addresses.

The resulting configuration is:

Configuring Multiple Instances of the Same Resource

When you use Junos PyEZ configuration Tables to configure structured resources on devices running Junos OS, you might need to configure multiple objects, or records, for the same structured resource. For example, you might configure multiple interfaces or users at the same time. To configure multiple objects for the same structured resource in a Junos PyEZ application, you must define the values for one object’s fields, call the append() method, and then repeat this process for each subsequent object.

For example, to configure multiple users, define the field values for the first user, and call the append() method. Then define the field values for the second user and call the append() method. The append() method builds the Junos XML data for the configuration change and adds it to the lxml object storing the master set of configuration changes. The method also automatically resets all of the fields back to their default values, as defined in the View, or to None if a field does not have a defined default.

The following example configures two user objects and commits the changes:

Note

If you do not call the append() method after configuring one of multiple objects for the same resource, the field values for the second object will overwrite the field values for the first object.

The following sample code configures the same two users using a more compact syntax:

Deleting Containers or Leaf Statements

In some cases, you might need to delete container or leaf statements in the configuration. When you use Junos PyEZ configuration Tables to manage structured resources, you can perform this operation in your application by setting the appropriate field value to {'operation' : 'delete'}. You must always define values for all key fields when deleting a container or leaf statement to indicate to which object the deletion applies.

Consider the following Junos PyEZ configuration Table and View:

To delete a leaf statement for the resource defined in the Table and View, set the value of the field corresponding to that statement to {'operation' : 'delete'}. The following example deletes the uid statement for user jsmith:

To delete a container from the configuration, the View must define a field for that container. In the example Table and View, the configuration scope defined by the set property is system/login. The View defines the field 'user', which maps to the system/login/user container. This definition enables you to delete user objects, if necessary. If you do not define a field for the container, you can only delete statements within the container, but you cannot delete the container itself.

To delete a container in the Junos PyEZ application, set the value of the field corresponding to the container to {'operation' : 'delete'}, and define the key field to indicate the object to delete. The following example deletes the user jsmith from the configuration:

The application prints the Junos XML configuration data returned by the get_table_xml() method. The user element with identifier 'jsmith' includes the operation="delete" attribute to instruct Junos OS to remove that object from the configuration.

Configuring Properties Corresponding to Junos XML Attributes

Some configuration mode commands, for example deactivate or protect, apply or remove a specific property, such as the inactive or protect property, to a configuration statement. In the CLI, this property is indicated by a tag preceding the configuration statement. The Junos XML configuration indicates this property using an XML attribute for the object.

For example, the following command deactivates the given interface.

[edit]
user@host# deactivate interfaces ge-1/0/2

When you view the configuration in the CLI, the inactive tag precedes the interface name.

[edit]
user@host# show interfaces

Similarly, in the Junos XML output, the <interface> element for the same interface includes the inactive="inactive" attribute.

user@host# show interfaces | display xml

Junos PyEZ configuration Tables enable you to define supported XML attributes for an object when configuring structured resources. Consider the following Junos PyEZ configuration Table and View:

To define the XML attribute for a given configuration object, set its field as defined by the View to a dictionary containing the attribute and its value. For example, to define an interface but immediately deactivate it, set the field corresponding to the <interface> element to {'inactive':'inactive'}. The following example configures and deactivates the given interface:

The application prints the Junos XML configuration data returned by the get_table_xml() method. The interface element with identifier 'ge-1/0/2' includes the inactive="inactive" attribute.

To activate an inactive object, set the View field corresponding to the inactive object to {'active':'active'}.

Similarly, to protect the configuration element or remove the protect attribute from a protected element, set the appropriate field value to {'protect':'protect'} or {'unprotect':'unprotect'}. For more information about XML attributes in the Junos OS configuration, see the Junos XML Management Protocol Developer Guide .

Using append() to Generate the Junos XML Configuration Data

When you use Junos PyEZ configuration Tables to configure structured resources on devices running Junos OS, you define the values for a resource’s fields and then call the append() method. Each call to the append() method generates the Junos XML configuration data for the current set of changes and adds it to the lxml object that stores the master set of configuration changes.

Calling the append() method generates the Junos XML configuration data for your resource. The configuration changes only include those fields that have either a default value defined in the View or a user-configured value. Fields that retain their initial value of None are ignored.

After building the XML, the append() method also resets all fields back to their default values, as defined in the View, or to None if a field does not have a defined default. Resetting the fields ensures that when you configure multiple objects in the same application, you do not set a field value for one object and then unintentionally use that value in subsequent calls to append() for a different object. Thus, you must define new values for all key-field fields for each call to append().

Note

Once you append nodes to the master set of configuration changes, you cannot undo the operation.

The append() method only adds the new changes to the lxml object containing the master set of configuration changes. You must explicitly call the set() method or the load() and commit() methods to load and commit the changes on the device.

Viewing Your Configuration Changes

When you use Junos PyEZ configuration Tables to configure structured resources on devices running Junos OS, you define the values for a resource’s fields and then call the append() method. Each call to the append() method generates the Junos XML configuration data for the current set of changes and adds it to the lxml object that stores the master set of configuration changes. At times, you might need to review the configuration data that has been constructed up to a certain point in the application, or you might want to view the differences between the candidate and active configurations after you load your configuration changes onto the device.

To retrieve the Junos XML configuration data containing your changes, call the Table object’s get_table_xml() method. The get_table_xml() method returns the XML configuration that has been constructed up to that point in the application. When you call the set() method or the load() and commit() methods, the application loads and commits this Junos XML configuration data on the device.

The following example calls the get_table_xml() method to retrieve the configuration changes and then stores them in the configXML variable. Prior to calling the append() method, the get_table_xml() method returns None. Thus, the application only serializes and prints the XML configuration data if the returned value is not None.

The get_table_xml() method only returns the Junos XML data for your configuration changes. You might also want to compare the candidate and active configurations after loading the configuration changes onto the device to review the differences before you commit the changes.

To retrieve the differences, you can call the lock(), load(), commit(), and unlock() methods separately and view your configuration differences by calling the pdiff() method after you load the data but before you commit it. The pdiff() method with an empty argument list compares the candidate configuration to the active configuration and prints the difference in patch format directly to standard output.

Controlling the RPC Timeout Interval

When you use Junos PyEZ configuration Tables to configure structured resources on devices running Junos OS, you can load and commit your configuration changes by calling the set() method or the load() and commit() methods. The set() and commit() methods use the RPC timeout value as defined in the device module. If you do not configure a new value for the Device timeout property, Junos PyEZ uses the default value of 30 seconds.

Large configuration changes might exceed the default or configured timeout value, causing the operation to time out before the configuration can be uploaded and committed on the device. To accommodate certain configuration changes that might require load and commit times that are longer than the default or configured timeout interval, set the timeout=seconds argument to an appropriate value when you call the set() or commit() method in your application. For example: