Export CVP Functionality to Ansible

In some network environments there is a separation of responsibility for the network infrastructure and the server side equipment. In these environments, different groups responsible for managing different equipment could use different tools for the job. This guide will discuss one of the several options for integrating Arista’s network management tool, CloudVision Portal (CVP), into an Ansible environment.

Summary

In this example, the environment uses Ansible as the configuration management tool for server provisioning but uses CVP for network management. The environment is set up to allow the server team to provision top of rack switch ports for servers using Ansible instead of having to be given access to CVP. The network operation team exports constrained functionality to the server team that can be configured using Ansible. This allows the server team to use their existing methodology consisting of Ansible playbooks to configure top of rack switch ports using predefined configuration templates.

Implementation

The Ansible/CVP integration is intended for an environment where the network equipment is primarily managed by a network team via CVP. The network team is responsible for exporting only the necessary functionality that the server team has access to and the server team is responsible for the network provisioning of ports using Ansible playbooks. The following sections will outline the separate network team and server team responsibilities for this setup.

Network Team

The network team is responsible for keeping the Ansible playbooks constrained to the specific host ports on top of rack switches that the server team is allowed to configure. The network team is also responsible for creating the Jinja configuration templates that the server team is allowed to use. The network team is able to constrain the server team to specific switches by creating the Ansible specific configlet and applying it to the switch. In this example, the configlets that the server team playbooks will be able to update have deterministic names with the format <switch_host_name>-server. If the server team attempts to run a playbook against a switch that does not have a configlet with the above name applied to it, an error will be raised letting the user know they are not allowed to configure that switch. ansibleconstraintconfiglet

The above image shows a configlet named ansible-192.168.1.21-server applied to switch ansible-192.168.1.21. The next constraint that the network team is responsible for is the specific ports on the switch that the server team has access to. This is done by putting configuration sections for ports the server team has access to into the previously mentioned configlet.

 ansibleconfigletinterfaceconstraint

The image above shows the contents of the same configlet previously mentioned. There are configuration sections for two ports and both are in their default non-configured state. This configlet will allow the Ansible playbook to be run by the server team to configure Ethernet3 or Ethernet4 on switch ansible-192.168.1.21. If a user provisioning a server accidentally runs a playbook that attempts to configure Ethernet1 as the host port for the server, the playbook will raise an error notifying the user they are not allowed to configure interface Ethernet1. The final piece the network team is responsible for is providing the Jinja formatted templates for different configuration options the server team can apply to a host port. An example template for a port configured for a single VLAN is shown below. single_attached_vlan.j2

interface Ethernet{{ switch_port }}
   description Host {{ server_name }} managed by Ansible and Jinja template
   switchport
   switchport mode access
   switchport access vlan {{ port_vlan }}
   no shutdown
!

Server Team

The server team will be responsible for building out and running the Ansible playbooks used for provisioning servers. The Ansible/CVP server module will be used to configure the servers top of rack network port. The module cv_server_provision (found here) accepts the following parameters. The module interacts with CVP using the required Python cvprac library.

  • server_name: The host name of the server being provisioned.
  • switch_name: The name of the switch that the server is connecting to. A rack to switch map could be defined so that a user can provide the rack name/id with the map to determine the top of rack switch name.
  • switch_port: The physical port number that the switch is connecting to.
  • port_vlan: The VLAN number to be applied to the port the switch is connecting to. This is only used if the template has port_vlan in it. If a template is used that requires port_vlan and no port_vlan is provided then the module will raise an error notifying the user.
  • template: The configuration template that will be used for configuring the port.
  • action: Action to take. Options include show, add, and remove.
    • show: No changes. Returns the existing configuration for the specified port in the results.
    • add: Adds the provided template configuration to the specified port. If the configuration is already in the configlet no change will be recorded.
    • remove: Defaults the specified port configuration. If the port is already in the default state no change will be recorded.
  • auto_run: If True the Ansible module will execute any task created when a configlet is updated. If False the task will remain pending in CVP for the network team to review and execute.

Example playbook and setup

hosts

[cvp]
<hostname> ansible_python_interpreter=<python path>

cvp

username: <username>
password: <password>
protocol: http

Note: CVP version 2017.1.0 and beyond only support https for the protocol.

server_provision.yaml

---
- hosts: cvp
  gather_facts: no
  connection: local

  tasks:
    - name: Provision Server
      cv_server_provision:
        host: "{{ inventory_hostname }}"
        username: "{{ username }}"
        password: "{{ password }}"
        protocol: "{{ protocol }}"
        server_name: <server name>
        switch_name: <switch name>
        switch_port: <port number>
        port_vlan: <vlan number>
        template: "single_attached_vlan.j2"
        action: "show"
        auto_run: True

Example return output when action = show

ok: [host name/address] => {
    "auto_run": true,
    "changed": false,
    "currentConfigBlock": "interface Ethernet3\n!",
    "host": "host name/address",
    "invocation": {
        "module_args": {
            ...
        },
        "module_name": "cv_server_provision"
    },
    "password": "password",
    "port": null,
    "portConfigurable": true,
    "port_vlan": "22",
    "protocol": "http",
    "server_name": "server name",
    "action": "show",
    "switchConfigurable": true,
    "switch_name": "ansible-192.168.1.21",
    "switch_port": "3",
    "taskCreated": false,
    "taskExecuted": false,
    "template": "single_attached_trunk.j2",
    "username": "username"
}

Example return output when action = add

changed: [host name/address] => {
    "auto_run": true,
    "changed": true,
    "fullConfig": "!\ninterface Ethernet3\n   description Host server name managed by Ansible and Jinja template\n   switchport\n   switchport mode access\n   switchport access vlan 22\n   no shutdown\n!\ninterface Ethernet4\n!",
    "host": "host name/address",
    "invocation": {
        "module_args": {
            ...
        },
        "module_name": "cv_server_provision"
    },
    "newConfigBlock": "interface Ethernet3\n   description Host server name managed by Ansible and Jinja template\n   switchport\n   switchport mode access\n   switchport access vlan 22\n   no shutdown\n!",
    "oldConfigBlock": "interface Ethernet3\n!",
    "password": "password",
    "port": null,
    "portConfigurable": true,
    "port_vlan": "22",
    "protocol": "http",
    "server_name": "server name",
    "action": "add",
    "switchConfigurable": true,
    "switch_name": "ansible-192.168.1.21",
    "switch_port": "3",
    "taskCreated": true,
    "taskExecuted": true,
    "taskId": "311",
    "template": "single_attached_vlan.j2",
    "updateConfigletResponse": "Configlet updated and task spanned successfully",
    "username": "username"
}

With properly setup configlets and templates by the network team the server team can use the cv_server_provision Ansible module in any of their playbooks for configuration and management of their server top of rack switch ports. Another CVP/Ansible integration example can be found here: CVP Telemetry and ZTP in Ansible environment

Note: The cv_server_provision module will be included in Ansible’s core modules as of version 2.4.