Hello World - A Simple Provisioning Example

Introduction

The following set of recipes will help you perform a basic provisioning task using the ZTPServer. There are some assumptions:

  • You have already installed the ZTPServer
  • You have performed the basic configuration to define which interface and port the server will run on.
  • You have a DHCP server running with option bootfile-name "http://<ZTPSERVER-URL>:<PORT>/bootstrap"; Sample config
  • Your test (v)EOS node can receive DHCP responses
  • Make sure the ztps process is not running

Note

If you would like to test this in a virtual environment, please see the packer-ztpserver Github repo to learn how to automatically install a ZTPServer with all of the complementary services (DHCP, DNS, NTP, XMPP, and SYSLOG). Both Virtual Box and VMware are supported.

Prepare Your Switch for Provisioning

Objective

I want to prepare my test device (vEOS or EOS) for use with the ZTPServer. This will put your switch into ZTP Mode, so backup any configs you want to save.

Solution

Log into your (v)EOS node, then:

switch-name> enable
switch-name# write erase
Proceed with erasing startup configuration? [confirm] y
switch-name# reload now

Explanation

ZTP Mode is enabled when a switch boots and there is no startup-config (or it’s empty) found in /mnt/flash/. Therefore, we use the write erase command to clear the current startup-config and use reload now to reboot the switch. When the switch comes up you will see it enter ZTP Mode and begin sending DHCP requests on all interfaces.

Add a Static Node Entry

Objective

I want to provision my switch based upon its System MAC Address.

Solution

Log into your (v)EOS node to get its MAC Address. If it’s in ZTP Mode, just log in with username admin:

switch-name> show version

Note

Copy the System MAC Address for later.

Confirm your ZTPServer Configuration will identify a node based upon its MAC:

admin@ztpserver:~# vi /etc/ztpserver/ztpserver.conf

Look for the line identifier and confirm it’s set to systemmac:

identifier = systemmac

Finally, let’s create a nodes directory for this device:

# Go to your data_root - by default it's /usr/share/ztpserver
admin@ztpserver:~# cd /usr/share/ztpserver

# Move to the nodes directory, where all node information is stored
admin@ztpserver:~# cd nodes

# Create a directory using the MAC Address you found earlier
admin@ztpserver:~# mkdir 001122334455

Explanation

A node is considered to be statically provisioned when a directory with its System ID is already located in the nodes/ directory.

Note that the System ID can be the node’s System MAC Address or its Serial Number. In this case we chose to use the systemmac since vEOS nodes don’t have a Serial Number by default.

Just adding this directory is not enough to provision the node. The remaining recipes will finish off the task.

Create a Startup-Config with Minimal Configuration

Objective

When my node is provisioned, I want it to be passed a static startup-config. This config will include some basic Management network info including syslog and ntp. It will set the admin user’s password to admin, and enable eAPI.

Solution

# Go to your data_root - by default it's /usr/share/ztpserver
admin@ztpserver:~# cd /usr/share/ztpserver

# Move to the specific node directory that you created earlier
admin@ztpserver:~# cd nodes/001122334455

# Create a startup-config
admin@ztpserver:~# vi startup-config

Copy and paste this startup-config, changing values where you see fit:

!
hostname test-node-1
ip name-server vrf default <DNS-SERVER-IP>
!
ntp server <NTP-SERVER-IP>
!
username admin privilege 15 role network-admin secret admin
!
interface Management1
 ip address <MGMT-IP-ADDRESS>/<SUBNET>
!
ip access-list open
 10 permit ip any any
!
ip route 0.0.0.0/0 <DEFAULT-GW>
!
ip routing
!
management api http-commands
 no shutdown
!
banner login
Welcome to $(hostname)!
This switch has been provisioned using the ZTPServer from Arista Networks
Docs: http://ztpserver.readthedocs.org/
Source Code: https://github.com/arista-eosplus/ztpserver
EOF
!
end

Explanation

When the ZTPServer receives a request from your node to begin provisioning, it will find the directory nodes/001122334455 and know that this node is statically configured. In this case, a startup-config must be present. In practice, the ZTPServer tells the node to perform the config_replace action with this file as the source.

Add Event Handler to Backup the startup-config to the ZTPServer

Objective

I want to backup the latest startup-config from my node so that if I make changes or have to replace the node I have the latest copy.

Note

By adding this, the node will perform an HTTP PUT and overwrite the nodes/001122334455/startup-config file.

Solution

# Go to your data_root - by default it's /usr/share/ztpserver
admin@ztpserver:~# cd /usr/share/ztpserver

# Move to the specific node directory that you created earlier
admin@ztpserver:~# cd nodes/001122334455

# Edit your startup-config
admin@ztpserver:~# vi startup-config

Add the following lines to your startup-config, changing values where needed:

event-handler configpush
 trigger on-startup-config
 ! For default VRF, make sure to update the ztpserver url
 action bash export SYSMAC=`FastCli -p 15 -c 'show ver | grep MAC | cut -d" " -f 5' | sed 's/[.]*//g'`; curl http://<ZTPSERVER-URL>:<PORT>/nodes/$SYSMAC/startup-config -H "content-type: text/plain" --data-binary @/mnt/flash/startup-config -X PUT
 ! For non-default VRF, update and use:
 ! action bash export SYSMAC=`FastCli -p 15 -c 'show ver | grep MAC | cut -d" " -f 5' | sed 's/[.]*//g'`; ip netns exec ns-<VRF-NAME> curl http://<ZTPSERVER-URL>:<PORT>/nodes/$SYSMAC/startup-config -H "content-type: text/plain" --data-binary @/mnt/flash/startup-config -X PUT

Explanation

By adding this line to the startup-config, this configuration will be sent down to the node during provisioning. From that point onward, the node will perform and HTTP PUT of the startup-config and the ZTPServer will overwrite the startup-config file in the node’s directory.

Install a Specific (v)EOS Version

Objective

I want a specific (v)EOS version to be automatically installed when I provision my node.

Note

This assumes that you’ve already downloaded the desired (v)EOS image from Arista.

Solution

Let’s create a place on the ZTPServer to host some SWIs:

# Go to your data_root - by default it's /usr/share/ztpserver
admin@ztpserver:~# cd /usr/share/ztpserver

# Create an images directory
admin@ztpserver:~# mkdir -p files/images

# SCP your SWI into the images directory, name it whatever you like
admin@ztpserver:~# scp admin@otherhost:/tmp/vEOS.swi files/images/vEOS_4.14.5F.swi

Now let’s create a definition that performs the install_image action:

# Go to your data_root - by default it's /usr/share/ztpserver
admin@ztpserver:~# cd /usr/share/ztpserver

# Move to the specific node directory that you created earlier
admin@ztpserver:~# cd nodes/001122334455

# Create a definition file
admin@ztpserver:~# vi definition

Add the following lines to your definition, changing values where needed:

---
name: static node definition
actions:
  -
    action: install_image
    always_execute: true
    attributes:
      url: files/images/vEOS_4.14.5F.swi
      version: 4.14.5F
    name: "Install 4.14.5F"

Note

The definition uses YAML syntax

Explanation

The definition is where we list all of the actions we want the node to execute during the provisioning process. In this case we are hosting the SWI on the ZTPServer, so we just define the url in relation to the data_root. We could change the url to point to another server altogether - the choice is yours. The benefit in hosting the file on the ZTPServer is that we perform an extra checksum step to validate the integrity of the file.

In practice, the node requests its definition during the provisioning process. It sees that it’s supposed to perform the install_image action, so it requests the install_image python script. It then performs an HTTP GET for the url. Once it has these locally, it executes the install_image script.

Start ZTPServer in Standalone Mode

Objective

Okay, enough reading and typing; let’s push some buttons!

Solution

Let’s run the ZTPServer in Standalone Mode since this is just a small test. Login to your ZTPServer:

# Start the ZTPServer - console loggin will appear
admin@ztpserver:~# ztps
INFO: [app:115] Logging started for ztpserver
INFO: [app:116] Using repository /usr/share/ztpserver
Starting server on http://<ZTPSERVER-URL>:<PORT>

Explanation

The easiest way to run the ZTPServer is in Standalone Mode - which is done by typing ztps in a shell. This will cause the configured interface and port to start listening for HTTP requests. Your DHCP server will provide the node with option bootfile-name "http://<ZTPSERVER-URL>:<PORT>/bootstrap" in the DHCP response, which lets the node know where to grab the bootstrap script.

A Quick Overview of the Provisioning Process for this Node

  1. GET /bootstrap: The node gets the bootstrap script and begins executing it. The following requests are made while the bootstrap script is being executed.
  2. GET /bootstrap/config: The node gets the bootstrap config which contains XMPP and Syslog information for the node to send logs to.
  3. POST /nodes: The node sends information about itself in JSON format to the ZTPServer. The ZTPServer parses this info and finds the System MAC. It looks in the nodes/ directory and finds a match.
  4. GET /nodes/001122334455: The node requests its definition and learns what resources it has to retrieve.
  5. GET /actions/install_image: The node retrieves the install_image script.
  6. GET /files/images/vEOS_4.14.5F.swi: The node retrieves the SWI referenced in the definition.
  7. GET /meta/files/images/vEOS_4.14.5F.swi: The node retrieves the checksum of the SWI for validation and integrity.
  8. GET /actions/replace_config: The node retrieves the replace_config script.
  9. GET /nodes/001122334455/startup-config: The node retrieves the startup-config we created earlier.
  10. GET /meta/nodes/001122334455/startup-config: The node retrieves the checksum of the startup-config.
  11. Node Applies Config and Reboots
  12. PUT /nodes/001122334455/startup-config: The node uploads its current startup-config.