The easiest way to install vspk is to use pip:

pip install vspk

Creating a session

# we'll use the 6.x API, but to use the 5.x API, replace v6 by v5_0
from vspk import v6 as vsdk

# enable logging. it makes debugging much easier
import logging
from vspk.utils import set_log_level
set_log_level(logging.DEBUG, logging.Streamhandler())

# create a new session for csproot
session = vsdk.NUVSDSession(

# start the session.
# we'll see later how to properly handle vspk exceptions.
# for now, just catch everything.
    logging.error('Failed to start the session')

If the session started successfully, session.user should be an instance of vspk.v6.nume.NUMe corresponding to csproot. Let’s wrap this in a function that we will reuse through this document:

from vspk import v6 as vsdk

def setup_logging():
    import logging
    from vspk.utils import set_log_level
    set_log_level(logging.DEBUG, logging.Streamhandler())

def start_csproot_session():
    session = vsdk.NUVSDSession(
        logging.error('Failed to start the session')
    return session.user

CRUD operations

Each vspk class correspond to a VSD entity. All the classes provide the same API to perform CRUD operations:

  • a create_child() method for creating children
  • a save() method to update the current entity
  • a delete() method to delete the current entity
  • a get() and a fetch() method to retrieve the current entity
  • multiple fetchers to retrieve children entities.

Creating objects

Here is an example of where we create an enterprise and a domain under csproot:

# we assume we have the setup_logging() and start_csproot_session() methods
# showed in the previous example

from vspk import v6 as vsdk
csproot = start_csproot_session()

# Create a new enterprise object. The only mandatory parameter is the name,
# so we give it directly to the contructor
new_enterprise = vsdk.NUEnterprise(name="new-corp")

# Create the enterprise on VSD.

# Create a new domaintemplate object.
new_domain_template = vsdk.NUDomainTemplate()
# The attributes can also be set on the object directly
new_domain_template.name = "new-dom-template"

# Create the domain on VSD.

Updating objects

Let’s change the name of the domain we just created. All we need to do to update an entity is change its attributes, and call save():

new_domain.name = "better-named-domain"

That’s it!

Deleting objects

Deleting objects dead simple: just call delete():


Fetching objects

Fetching the current entity

Fetching the current entity is pretty simple:


There are two reasons why we would need to fetch the current entity:

  • to get an up-to-date representation of the entity, in case it has been updated on the VSD by someone else
  • to retrieve an entity from its UUID For example, if we know the UUID of a subnet on VSD, we could do:
my_subnet = vsdk.NUSubnet(id="123e4567-e89b-12d3-a456-426655440000")

# Now, the attributes of the object are populated with data from VSD. We
# can for instance print the subnet's name:
logging.info("Fetched subnet %s!" % my_subnet.name)

Fetching child entities

Each child entity has a corresponding fetcher. Calling the fetcher will populate it. For instance, assuming we have vports under the subnet we just fetched, we could retrieve them like this:

# fetch the vports
for vport in my_subnet.vports:
    logging.info("vport: %s" % vport.name)

    # fetch the host interfaces under the current vport
    for interface in vport.host_interfaces:
        logging.info("host ip: %s" % interface.ip_address)

Since get returns itself, we can make this shorter:

for vport in my_subnet.vports.get():
    logging.info("vport: %s" % vport.name)

    for interface in vport.host_interfaces.get():
        logging.info("host ip: %s" % interface.ip_address)


By default, fetchers fetch all the child entities, which can lead to huge responses. Fortunately, the API offers filters on some attributes, and vspk provides a way to use them:

# get all the bridge vports in the current domain:
for vport in domain.vports.get(filter='type is "BRIDGE"'):
    # do something

Assigning entities

Some entities do not follow the parent/children relationship. For example, users are not children of groups, they belong to one or multiple groups. Similarly, policy groups are assigned to vports. To assign entities to another entity, we use the assign() method:

entity.assign(assigned_entities_list, assigned_entities_class)

This method takes two arguments:

  • the list of entities to be assigned
  • the class of the assigned entities

For example, to add a user “bob” to a group “engineers”:

# Get the "engineers" group.
# get_first() is a convenient shortcut for get()[0], that returns None if
# no entity was fetched.
engineers = enterprise.groups.get_first(filter="name is 'engineers'")

# Get the user we want to add to the group
bob = enterprise.users.get_first(filter="userName is 'bob'")

# Fetch the users already assigned to this group
current_users = engineers.users.get()

    # We assign the list of *all* the users, not only "bob"
    # We need to specify the class of the entities we are assigning

To un-assign resources, we just re-assign a list without these resources. To remove the user “bob” we just added, we could to this:

# Fetch the assigned users
assigned_users = engineers.users.get()

# Make  new list of users without "bob"
new_assigned_users = [user if user.user_name != "bob" for user in assigned_users]

# Assign this new list
engineers.assign(new_assigned_users, vsdk.NUUser)

To un-assign all the entities, assign an empty list:

engineers.assign([], vsdk.NUUser)

Error handling

All of the previous methods raise a bambou.exception.BambouHTTPError when they fail, which contains some interesting information, like the HTTP status code. It can be useful to catch these exceptions:

from bambou.exceptions import BambouHTTPError

# We assume we have a parent trying to create a child.

except BambouHTTPError as exc:
    response = exc.connection.response
    if response.status_code == 409:
        # the entity probably already exists, so we just ignore this error:
        logging.Error("Failed to create entity: %s" % exc.message())
        # re-raise the exception