pynipap - a Python NIPAP client library

pynipap is a Python client library for the NIPAP IP address planning system. It is structured as a simple ORM. To make it easy to maintain it’s quite “thin”, passing many arguments straight through to the backend. Thus, also the pynipap-specific documentation is quite thin. For in-depth information please look at the main NIPAP API documentation.

There are four ORM-classes:

Each of these maps to the NIPAP objects with the same name. See the main NIPAP API documentation for an overview of the different object types and what they are used for.

There are also a few supporting classes:

And a bunch of exceptions:

General usage

pynipap has been designed to be simple to use.

Preparations

Make sure that pynipap is accessible in your sys.path, you can test it by starting a python shell and running:

import pynipap

If that works, you are good to go!

To simplify your code slightly, you can import the individual classes into your main namespace:

import pynipap
from pynipap import VRF, Pool, Prefix

Before you can access NIPAP you need to specify the URL to the NIPAP XML-RPC service and the authentication options to use for your connection. NIPAP has a authentication system which is somewhat involved, see the main NIPAP documentation.

The URL, including the user credentials, is set in the pynipap module variable xmlrpc_uri as so:

pynipap.xmlrpc_uri = "http://user:pass@127.0.0.1:1337/XMLRPC"

If you want to access the API externally, from another host, update the corresponding lines in the nipap.conf file. Here you can also change the port.

listen = 0.0.0.0              ; IP address to listen on.
port = 1337             ; XML-RPC listen port (change requires restart)

The minimum authentication options which we need to set is the authoritative_source option, which specifies what system is accessing NIPAP. This is logged for each query which alters the NIPAP database and attached to each prefix which is created or edited. Well-behaved clients are required to honor this and verify that the user really want to alter the prefix, when trying to edit a prefix which last was edited by another system. The AuthOptions class is a class with a shared state, similar to a singleton class; that is, when a first instance is created each consecutive instances will be copies of the first one. In this way the authentication options can be accessed from all of the pynipap classes.

a = AuthOptions({
        'authoritative_source': 'my_fancy_nipap_client'
    })

After this, we are good to go!

Accessing data

To fetch data from NIPAP, a set of static methods (@classmethod) has been defined in each of the ORM classes. They are:

  • get() - Get a single object from its ID.
  • list() - List objects matching a simple criteria.
  • search() - Perform a full-blown search.
  • smart_search() - Perform a magic search from a string.

Each of these functions return either an instance of the requested class (VRF, Pool, Prefix) or a list of instances. The search() and smart_search() functions also embeds the lists in dicts which contain search meta data.

The easiest way to get data out of NIPAP is to use the get()-method, given that you know the ID of the object you want to fetch:

# Fetch VRF with ID 1 and print its name
vrf = VRF.get(1)
print(vrf.name)

To list all objects each object has a list()-function.

# list all pools
pools = Pool.list()

# print the name of the pools
for p in pools:
    print(p.name)

Each of the list functions can also take a spec-dict as a second argument. With the spec you can perform a simple search operation by specifying object attribute values.

# List pools with a default type of 'assignment'
pools = Pool.list({ 'default_type': 'assignment' })

Performing searches

Searches are easiest when using the object’s smart_search()-method:

#Returns a dict which includes search metadata and 
#a 'result' : [array, of, prefix, objects]
search_result = Prefix.smart_search('127.0.0.0/8')
prefix_objects = search_result['result']
prefix_objects[0].description
prefix_objects[0].prefix

You can also send query filters.

#Find the prefix for Vlan 901
vlan = 901
vlan_query = { 'val1': 'vlan', 'operator': 'equals', 'val2': vlan }
vlan_901 = Prefix.smart_search('', { }, vlan_query)['result'][0]
vlan_901.vlan

The following operators can be used.

* 'and'
* 'or'
* 'equals_any'
* '='
* 'equals'
* '<'
* 'less'
* '<='
* 'less_or_equal'
* '>'
* 'greater'
* '>='
* 'greater_or_equal'
* 'is'
* 'is_not'
* '!='
* 'not_equals'
* 'like': '
* 'regex_match'
* 'regex_not_match'
* '>>':
* 'contains'
* '>>='
* 'contains_equals'
* '<<'
* 'contained_within'
* '<<='
* 'contained_within_equals'

Saving changes

Changes made to objects are not automatically saved. To save the changes, simply run the object’s save()-method:

vrf.name = "Spam spam spam"
vrf.save()

Error handling

As is customary in Python applications, an error results in an exception being thrown. All pynipap exceptions extend the main exception NipapError. A goal with the pynipap library has been to make the XML-RPC-channel to the backend as transparent as possible, so the XML-RPC Faults which the NIPAP server returns in case of errors are converted and re-thrown as new exceptions which also they extend NipapError, for example the NipapDuplicateError which is thrown when a duplicate key error occurs in NIPAP.

Classes

class pynipap.AuthOptions(options=None)

A global-ish authentication option container.

Note that this essentially is a global variable. If you handle multiple queries from different users, you need to make sure that the AuthOptions-instances are set to the current user’s.

exception pynipap.NipapAuthError

General NIPAP AAA error

exception pynipap.NipapAuthenticationError

Authentication failed.

exception pynipap.NipapAuthorizationError

Authorization failed.

exception pynipap.NipapDuplicateError

A duplicate entry was encountered

exception pynipap.NipapError

A generic NIPAP model exception.

All errors thrown from the NIPAP model extends this exception.

exception pynipap.NipapExtraneousInputError

Extraneous input

Most input is passed in dicts, this could mean an unknown key in a dict.

exception pynipap.NipapInputError

Something wrong with the input we received

A general case.

exception pynipap.NipapMissingInputError

Missing input

Most input is passed in dicts, this could mean a missing key in a dict.

exception pynipap.NipapNoSuchOperatorError

A non existent operator was specified.

exception pynipap.NipapNonExistentError

Thrown when something can not be found.

For example when a given ID can not be found in the NIPAP database.

exception pynipap.NipapValueError

Something wrong with a value we have

For example, trying to send an integer when an IP address is expected.

class pynipap.Pool

An address pool.

classmethod from_dict(parm, pool=None)

Create new Pool-object from dict.

Suitable for creating objects from XML-RPC data. All available keys must exist.

classmethod get(id)

Get the pool with id ‘id’.

classmethod list(spec=None)

List pools.

Maps to the function nipap.backend.Nipap.list_pool() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

remove()

Remove pool.

Maps to the function nipap.backend.Nipap.remove_pool() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

save()

Save changes made to pool to NIPAP.

If the object represents a new pool unknown to NIPAP (attribute id is None) this function maps to the function nipap.backend.Nipap.add_pool() in the backend, used to create a new pool. Otherwise it maps to the function nipap.backend.Nipap.edit_pool() in the backend, used to modify the pool. Please see the documentation for the backend functions for information regarding input arguments and return values.

classmethod search(query, search_opts=None)

Search pools.

Maps to the function nipap.backend.Nipap.search_pool() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

Perform a smart pool search.

Maps to the function nipap.backend.Nipap.smart_search_pool() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

class pynipap.Prefix

A prefix.

classmethod find_free(vrf, args)

Finds a free prefix.

Maps to the function nipap.backend.Nipap.find_free_prefix() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

classmethod from_dict(pref, prefix=None)

Create a Prefix object from a dict.

Suitable for creating Prefix objects from XML-RPC input.

classmethod get(id)

Get the prefix with id ‘id’.

classmethod list(spec=None)

List prefixes.

Maps to the function nipap.backend.Nipap.list_prefix() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

remove(recursive=False)

Remove the prefix.

Maps to the function nipap.backend.Nipap.remove_prefix() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

save(args=None)

Save prefix to NIPAP.

If the object represents a new prefix unknown to NIPAP (attribute id is None) this function maps to the function nipap.backend.Nipap.add_prefix() in the backend, used to create a new prefix. Otherwise it maps to the function nipap.backend.Nipap.edit_prefix() in the backend, used to modify the VRF. Please see the documentation for the backend functions for information regarding input arguments and return values.

classmethod search(query, search_opts=None)

Search for prefixes.

Maps to the function nipap.backend.Nipap.search_prefix() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

Perform a smart prefix search.

Maps to the function nipap.backend.Nipap.smart_search_prefix() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

class pynipap.Pynipap(id=None)

A base class for the pynipap model classes.

All Pynipap classes which maps to data in NIPAP (VRF, Pool, Prefix) extends this class.

id = None

Internal database ID of object.

class pynipap.Tag(id=None)

A Tag.

classmethod from_dict(tag=None)

Create new Tag-object from dict.

Suitable for creating objects from XML-RPC data. All available keys must exist.

name = None

The Tag name

classmethod search(query, search_opts=None)

Search tags.

For more information, see the backend function nipap.backend.Nipap.search_tag().

class pynipap.VRF

A VRF.

description = None

VRF description, as a string.

free_addresses_v4 = None

Number of free IPv4 addresses in this VRF

free_addresses_v6 = None

Number of free IPv6 addresses in this VRF

classmethod from_dict(parm, vrf=None)

Create new VRF-object from dict.

Suitable for creating objects from XML-RPC data. All available keys must exist.

classmethod get(id)

Get the VRF with id ‘id’.

classmethod list(vrf=None)

List VRFs.

Maps to the function nipap.backend.Nipap.list_vrf() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

name = None

The name of the VRF, as a string.

num_prefixes_v4 = None

Number of IPv4 prefixes in this VRF

num_prefixes_v6 = None

Number of IPv6 prefixes in this VRF

remove()

Remove VRF.

Maps to the function nipap.backend.Nipap.remove_vrf() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

rt = None

The VRF RT, as a string (x:y or x.x.x.x:y).

save()

Save changes made to object to NIPAP.

If the object represents a new VRF unknown to NIPAP (attribute id is None) this function maps to the function nipap.backend.Nipap.add_vrf() in the backend, used to create a new VRF. Otherwise it maps to the function nipap.backend.Nipap.edit_vrf() in the backend, used to modify the VRF. Please see the documentation for the backend functions for information regarding input arguments and return values.

classmethod search(query, search_opts=None)

Search VRFs.

Maps to the function nipap.backend.Nipap.search_vrf() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

Perform a smart VRF search.

Maps to the function nipap.backend.Nipap.smart_search_vrf() in the backend. Please see the documentation for the backend function for information regarding input arguments and return values.

total_addresses_v4 = None

Total number of IPv4 addresses in this VRF

total_addresses_v6 = None

Total number of IPv6 addresses in this VRF

used_addresses_v4 = None

Number of used IPv4 addresses in this VRF

used_addresses_v6 = None

Number of used IPv6 addresses in this VRF

class pynipap.XMLRPCConnection

Handles a shared XML-RPC connection.

pynipap.nipap_db_version()

Get schema version of database we’re connected to.

Maps to the function nipap.backend.Nipap._get_db_version() in the backend. Please see the documentation for the backend function for information regarding the return value.

pynipap.nipapd_version()

Get version of nipapd we’re connected to.

Maps to the function nipap.xmlrpc.NipapXMLRPC.version() in the XML-RPC API. Please see the documentation for the XML-RPC function for information regarding the return value.